library(tidyverse)     # for data cleaning and plotting
library(lubridate)     # for date manipulation
library(openintro)     # for the abbr2state() function
library(gplots)        # for col2hex() function
library(RColorBrewer)  # for color palettes
library(ggthemes)      # for more themes (including theme_map())
library(plotly)        # for the ggplotly() - basic interactivity
library(gganimate)     # for adding animation layers to ggplots
library(transformr)    # for "tweening" (gganimate)
library(gifski)        # need the library for creating gifs but don't need to load each time
library(shiny)         # for creating interactive apps
library(lubridate)     # for date manipulation
library(ggthemes)      # for even more plotting themes
library(janitor)  
library(treemapify)
theme_set(theme_minimal())
XOM <- read_csv("XOM.csv")
XOM <- XOM %>%
  select(-Open, -High, -Low, -`Adj Close`) %>% 
  mutate(Sector="Energy",
         Company= "XOM") %>% 
   mutate(return = (Close - 70.90)/ 70.90 * 100) %>% 
  mutate(shares = 434167944) %>% 
  mutate(market_cap = shares * Close)



CVX <- read_csv("CVX.csv")
CVX <- CVX %>%
  select(-Open, -High, -Low, -`Adj Close`) %>%
  mutate(Sector="Energy",
         Company= "CVX") %>%
   mutate(return = (Close - 121.43)/ 121.43 * 100) %>% 
  mutate(shares = 197023923) %>% 
  mutate(market_cap = shares * Close)
  

RDS_A <-read_csv("RDS-A.csv")
RDS_A <- RDS_A %>%
  select(-Open, -High, -Low, -`Adj Close`) %>%
  mutate(Sector="Energy",
         Company= "RDS_A")%>%
   mutate(return = (Close - 59.74)/ 59.74 * 100) %>% 
  mutate(shares = 8058300000) %>% 
  mutate(market_cap = shares * Close)
  

energy <- rbind(XOM,CVX,RDS_A)
AMT <- read_csv("AMT.csv")
AMT <- AMT %>%
  select(-Open, -High, -Low, -`Adj Close`) %>%
  mutate(Sector="Real Estate",
         Company= "AMT")%>%
  mutate(return = (Close - 228.50)/ 228.50 * 100) %>% 
  mutate(shares = 46014457) %>% 
  mutate(market_cap = shares * Close)
  
KE <- read_csv("KE.csv")
KE <- KE %>%
  select(-Open, -High, -Low, -`Adj Close`) %>%
  mutate(Sector="Real Estate",
         Company= "KE")%>%
  mutate(return = (Close - 17.690)/ 17.690 * 100) %>% 
  mutate(shares = 2492397900) %>% 
  mutate(market_cap = shares * Close)
  

PLD <- read_csv("PLD.csv")
PLD <- PLD %>%
  select(-Open, -High, -Low, -`Adj Close`) %>%
  mutate(Sector="Real Estate",
         Company= "PLD")%>%
  mutate(return = (Close - 88.40    )/ 88.40 * 100) %>% 
  mutate(shares = 739500000) %>% 
  mutate(market_cap = shares * Close)
 
real_estate <- rbind(AMT,KE,PLD)
BHP <-read_csv("BHP.csv")
BHP <- BHP%>%
  select(-Open, -High, -Low, -`Adj Close`) %>%
  mutate(Sector="Material",
         Company= "RDS_A") %>%
  mutate(return = (Close - 54.92)/ 54.92 * 100) %>% 
  mutate(shares = 248421053) %>% 
  mutate(market_cap = shares * Close)
  
LIN <-read_csv("LIN.csv")
LIN <- LIN %>%
  select(-Open, -High, -Low, -`Adj Close`) %>%
  mutate(Sector="Material",
         Company= "LIN") %>%
  mutate(return = (Close - 210.74)/ 210.74 * 100) %>% 
  mutate(shares = 52915292) %>% 
  mutate(market_cap = shares * Close)

RIO <-read_csv("RIO.csv")
RIO <- RIO %>%
  select(-Open, -High, -Low, -`Adj Close`) %>%
  mutate(Sector="Material",
         Company= "RIO")%>%
  mutate(return = (Close - 59.89)/ 59.89 * 100) %>% 
  mutate(shares = 170077427) %>% 
  mutate(market_cap = shares * Close)
  
material <- rbind(BHP,LIN,RIO)
communication_services <- rbind(GOOGL, TCEHY, FB)
utilities <- rbind(NEE, ENLAY, IBDSF)
financials <- rbind(JPM, BRKA, V)
communication_discretionary <- rbind(AMZN, TSLA, BABA)
consumer_staple <- rbind(WMT, NSRGF, PG)
tech <- rbind(AAPL,MSFT,NVDA)
industrials <- rbind(HON,UNP,UPS)
health <- rbind(JNJ,UNH,RHHBY)
sp <- rbind(communication_services, utilities, financials, communication_discretionary, consumer_staple,
            tech, industrials, health, real_estate, material, energy, SPY)

Introduction:

We have seen multiple changes around the world after one year. The main reason for that is because of the coronavirus pandemic. Firstly thought of as a common flu in Wuhan, China, the pandemic has spread around the world, with more than 100 million cases and more than 2.5 million deaths. Especially in the US, we have seen around 30 million cases with more than 500,000 deaths resulting from the pandemic (according to Worldometer) . Coronavirus has changed our perspective in multiple areas, however, in this blog post, we focus specifically on its impact on companies and sectors in the US stock market. We will see what are the changes in stock price, in market capitalization as well as how each sector has changed after the pandemic.

First, as we have more than 2,800 companies trading in the New York Stock Exchange (NYSE), it is really difficult to do it in a short period of time. Instead, we used the website Yahoo Finance to find the data for the 3 companies with highest market cap in different 11 sectors: Communication Discretionary, Communication Services, Consumer Staples, Energy, Financials, Health Care, Industrials, Material, Real Estate, Technology, Utilities. Then, to compare the results from different sectors to the wider market, we used the SPY, which is an ETF for the S&P 500 that tracks the changes in the value of the biggest 500 companies in the market. We classified the SPY data as “All fields”. We tracked the data from 2020-01-02 to 2021-03-04, using the volume and the closing price. We assembled the data in a time series format creating dummy variables for each sector, then we chose to use the closing price given that it shows the final value that market participants attribute to a share after trading, providing a more realistic depiction of its value. Then, we calculated the Cumulative Rate of Return everyday by using the following formula:

\[ return = \frac{Price_i - Price_1}{Price_1 * 100} \]

We also obtained the market cap by multiplying the number of market shares of each company by the Closing price each day. We retrieved the number of shares from the SEC filing website.

After we have found the way to conduct research with our data, we have created three main questions:

a. Which companies and which sectors have performed the best during the period? What is the proportion of negative and positive daily average return for each sector?
b. What are the changes in market capitalization?
c. Which companies have the highest trading volume? Which sectors have the highest number of trading?

The performance of companies and the sectors:

Return by sectors:

A <- sp %>%
  group_by(Sector,Date)%>%
  summarise(return=mean(return))%>%
  ggplot(aes(y=return,x=Date, color=Sector))+
  geom_line()+
  labs(y="",
       x="",
       subtitle = "Date: {frame_along}",
       title = "Changing Rate of Return for Different Sectors")+
  facet_wrap(~Sector,scales="free_y")+
  scale_x_date(date_labels = "%y-%m")+
  theme(legend.position = 0,axis.text.x = element_text(size = 8))+
  transition_reveal(Date)
  animate(A,width=600,height=400)

anim_save("All_Line.gif")

moving_return_sector <- drop_na(sp) %>% 
  group_by(Date, Sector) %>% 
  summarise(return = mean(return) / 100) %>% 
  ungroup() %>% 
  group_by(Date) %>% 
  #summarise(daily_return = sum(return)) %>% 
  #mutate(total_return_period = cumsum(daily_return)) %>% 
  top_n(n = 10, wt = return) %>%  
  arrange(Date, return) %>% 
  mutate(rank = 1: n()) %>% 
  ggplot(aes(y = factor(rank), x = return,
             fill = return)) + 
  geom_col() + 
  geom_text(aes(label = Sector),
            color = "black", hjust = "left", x = 0) +
  labs(title = "Change in rate of return in different sectors",
       subtitle = "Date: {frame_time}",
       x = "",
       y = "") +
  theme(axis.line = element_blank(),
        panel.grid = element_blank(),
        axis.text.y = element_blank(),
        legend.position = "none")  +
  scale_fill_viridis_c() + 
  transition_time(Date) 

animate(moving_return_sector, nframes = 200, duration = 45)
anim_save("moving_return_sector.gif")

Overall, it seems that the return for the Communication Discretionary is consistently growing, almost in a positively linear way. The lowest return is still not below 0. Changes in return of Communication Services and Technology follow a similar trend to that of Communication Discretionary in shape, but have a smaller magnitude (-20~ 60 for CS, -25~100 for T, compared to 0~300 for CD). Consumer Staples fluctuated mildly, falling sharply first to -10 and rebounding quickly, then growing steadily to finally decrease back to 0 return. The situation for the Energy and Financials sectors is the worst. Since the first day, Energy’s cumulative return is negative. Only the last month is positive for the Financials sector. Health Care, Industrials, Material, Real Estate, and Utilities followed a similar trend, but these sectors’ conditions are better than that of Energy and Financials. Health Care, Industrials, Material, Real Estate, and Utilities have similar trends compared to the overall market. In general, the return sharply dropped from 2020-1-1 to April 2020 and then rebounded at a lower rate, back to 0 in August 2020. After, it oscillated up and down until 2020 November and then continuously increased slowly. So far, return as a whole is 20%.

return_type <- sp %>% 
  filter(Sector!="All field") %>% 
  select(-Close, -Volume) %>% 
  group_by(Date, Sector) %>% 
  mutate(avg_return = mean(return),
         type_return = ifelse(avg_return<0, "negative", "positive"))%>% 
  ungroup() %>% 
  group_by(Sector) %>% 
  mutate(`Proportion negative` = mean(type_return == "negative"),
         `Proportion positive` = mean(type_return == "positive")) %>% 
  pivot_longer(cols = `Proportion negative`:`Proportion positive`,
               names_to = "prop_type",
               values_to = "prop") %>% 
  summarize(Sector, prop_type, prop) %>%
  distinct(Sector, prop_type, prop)


return_type %>% 
  ggplot(aes(x = prop, y = prop_type, fill = prop_type )) + 
  geom_col()+
  geom_text(aes(label = round(prop,digits = 2)), size = 2)+
  facet_wrap(~Sector)+
  labs(title = "Proportions of negative and positive daily average returns per sector",
       fill = "Type of return",
       x = "", 
       y = "")+
  theme(legend.position = 0,
        panel.grid.major.y = element_blank(),
        panel.grid.minor.y=element_blank())

Additionally, we try to see the proportion of time in which the average of the cumulative return of the best stocks per sector have been over or under the base price. In here, it comes as no surprise as Communication Discretionary was the sector with the highest proportion of positive returns relative to the negative returns. This meaning, that 97% of the time the Communication Discretionary sector had positive returns relative to the initial price. Had a person bought shares of the companies in this sector on January 2nd, they would have slept peacefully 97% of the time. On the other hand, the Energy sector was the sector with the highest proportion of negative returns relative to positive returns. As we can see, the pandemic affected different sectors in a different way. The least affected sectors are Communication Discretionary and Technology, one of the reasons being that their consumption doesn’t require in person presence. In the case of energy, a drop in the demand of petroleum as a consequence of the lockdown in different countries decreased their prices. Given that oil companies’ revenue depends on price, the investors sold their shares expecting losses on the oil industry. The Financials sector was also drastically affected, as the FED lowered the interest rates and there were negative interest rates in Europe, understanding that banks are the suppliers of capital, lower (or negative) interest rates affect banks’ revenue.

Return by companies:

moving_return_company <- drop_na(sp) %>% 
  group_by(Date, Company) %>% 
  select(-Volume, -Sector) %>% 
  ungroup() %>% 
  group_by(Date) %>% 
  mutate(return = return / 100) %>% 
  top_n(n = 10, wt = return) %>%  
  arrange(Date, return) %>% 
  mutate(rank = 1: n()) %>% 
  ggplot(aes(y = factor(rank), x = return,
             fill = return)) + 
  geom_col() + 
  geom_text(aes(label = Company),
            color = "black", hjust = "left", x = 0) +
  labs(title = "Rate of return changes in companies",
       subtitle = "Date: {frame_time}",
       x = "",
       y = "") +
  theme(axis.line = element_blank(),
        panel.grid = element_blank(),
        axis.text.y = element_blank(),
        legend.position = "none")  +
  scale_fill_viridis_c() + 
  transition_time(Date) 
animate(moving_return_company, nframes = 200, duration = 45)
anim_save("moving_return_company.gif")

When we go deeper into each company in the field, it will be Tesla that grows the most during the period. Tesla’s stock price has increased more than 9 times for the period, followed by Nvidia as the company tripled in value. After that, we can see Apple, Amazon, Microsoft or Facebook increased quite heavily during the period, all increasing by 100-150%. Given that the Energy and Financial sectors did not see an increase in the stock price, it comes as no surprise that we can’t see any companies in those sectors in the top ten list.

When we look closer at the shorter period, in March or April, we can see Walmart (one of the companies in the Consumer Staples section) that was in top 10 companies with the greatest return. However, after this period, it was still companies in Communication Discretionary and Technology that have the highest return such as Tesla, Nvidia, Microsoft, Amazon or Apple.

The change in market capitalization for each sector and for the company:

l <- "squarified"
p2<- 
  sector_data %>% 
  ungroup() %>% 
  # filter(date == "2020-01-10") %>%
  ggplot( aes(area = percentage ,
              fill = sector, 
              label = label,
              group= date)) +
  geom_treemap(layout = l) +
  geom_treemap_text(layout=l) +
  labs(title = "Distribution of Market Cap in by Sector in {current_frame}")+
  theme(legend.position = "none")     +
  transition_manual(date)
animate(p2, duration = 120)

anim_save("sp_market_cap_treemap_by_sector_anim.gif")
knitr::include_graphics("sp_market_cap_treemap_by_sector_anim.gif")

Looking at the distribution of market cap by sector during the Covid-19 period, it is seen clearly that Communication Discretionary and Technology have consistently been the top first and second largest sectors respectively with combined shares at more than 60%. The two sectors remain the leading sectors throughout the period from January 2020 to March 2021.

Consumer Discretionary is the biggest sector which accounts for around 46% of the entire market cap. The highest percentage of this sector was 49.7888% in late October 2020. This increasing trend started in January and hit the peak in October 2020 before having a decreasing trend from October to March the next year. The next sector, Technology, also had an increasing percentage over time as the area in the graph increased. This percentage of market cap for this sector started from 19.85% in January 2020, at 21.48% in the 1st Quarter in April 2020 and at 24.17% in November 2020. The max for this sector was 26.84%.

sector_data <-
  sp %>%
  clean_names()  %>%
  filter(sector != "All field") %>%
  group_by(date, sector) %>%
  summarise(market_cap = sum(market_cap)) %>%
  mutate(percentage = 100*market_cap/sum(market_cap)) %>%
  mutate(label = paste(sector, paste(round(percentage,2),"%"), sep="\n") )
company_data <-
  sp %>% 
  clean_names() %>% 
  filter(sector != "All field") %>%
  group_by(date, company) %>% 
  summarise(market_cap = sum(market_cap)) %>%
  mutate(percentage = 100*market_cap/sum(market_cap)) %>%
  mutate(label = paste(company, paste(round(percentage,2),"%"), sep="\n") )
  
p3<- 
  company_data %>% 
  ungroup() %>% 
  # filter(date == "2020-01-10") %>%
  ggplot( aes(area = percentage ,
              fill = company, 
              label = label,
              group= date)) +
  geom_treemap() +
  geom_treemap_text() +
  labs(title = "Distribution of Market Cap by Company in {current_frame}")+
  theme(legend.position = "none")     +
  transition_manual(date)
animate(p3, duration = 120)

anim_save("sp_market_cap_treemap_by_company_anim.gif")

The distribution of market cap by company graph shows the top 20 companies that have the greatest amount of market cap proportion. Apple (AAPL), Amazon (AMZN), and Microsoft (MSFT) are the top three companies that are from the top two sectors: Communication Discretionary and Technology. From this we can see how the two sectors are the dominant by looking which companies have the greatest market cap.

The change in trading volume for each sector.

volume <- sp %>% 
  filter(Sector!="All field") %>% 
  select(-Close, -return) %>%
  mutate(month = month(Date,label = TRUE),
         year = year(Date)) %>% 
  group_by(Sector, month, year) %>% 
  summarize(`Total volume` = sum(Volume)) %>% 
  ungroup() %>% 
  mutate(date = ymd(paste(year,month,"01"))) %>% 
  mutate(Sector = fct_reorder(Sector, `Total volume`, median, .desc = TRUE)) %>% 
  ggplot(aes(x = date, y = `Total volume`, fill = Sector))+
  geom_col()+
  labs(title = "Monthly amount of transactions per sector last year",
       y = "",
       x = "")+
  scale_x_date(date_labels = "%b", date_breaks = "3 months")+
  scale_y_continuous(labels = scales::comma)+
  theme(legend.position = "none",
        panel.grid.major.x = element_blank(),
        panel.grid.major.y = element_blank(),
        panel.grid.minor.y =element_blank())+
  facet_wrap(~Sector)

ggplotly(volume,
         tooltip = c("y"))

The bar graph shows the sum of the monthly transactions for the three biggest companies in each sector. We can see that the sector with the highest volume is Technology, and the sector with the lowest volume is the Real Estate sector. The high volumes in the Technology sector potentially reflect that investors preferred large technology companies over the pandemic.

real_estate %>% 
  ggplot(aes(x = Date, y = return, color = Company)) +
  geom_line()+
  labs(title = "Real Estate biggest companies' returns over the past year",
       y = "Return", 
       x = "")

tech %>% 
  ggplot(aes(x = Date, y = return, color = Company)) +
  geom_line()+
  labs(title = "Technology biggest companies' returns over the past year",
       y = "Return", 
       x = "")

These companies have large market caps, and given that the 5 largest companies in the Technology sector account for a large fraction of the S&P 500, these “blue chip” companies are expected to have larger volumes. One of the reasons is their liquidity. They are very liquid because many people are trading them; therefore, you can find buyers and sellers quickly. As a result there are no price distortions as a consequence of delays in transactions. On the other hand, this could be just a continuation of past trends, given that the technology sector has been the most popular in the last years.

Another potential explanation is that Technology stocks are always more risky given the larger returns; therefore, there are major price swings that cause people to increase their transactions. Also, larger volumes reflect the strength of price changes during the pandemic. In the case of Real Estate, low volumes reflect the lack of strength in price changes, reflected on subtle changes in the cumulative returns graphed. As we can see in the graph for Real Estate companies, the trend is flatter and the changes are of a smaller magnitude, proving that there weren’t significant changes in return. Therefore,there weren’t many changes in the demand or supply of Real Estate stock.

We can also observe that in periods with low prices, the volume tends to increase. In this case, it was in March given the declaration of sanitary emergency and the first COVID-19 cases in the country. This is because many people attempt to sell their shares quickly while other investors seek to buy shares at lower prices.

Conclusion:

The following post has shown some of the key changes within the period. It has shown how each sector has changed and how each company reacts to the pandemic. Some companies thrived, like Tesla, however, some took lots of time to recover, especially in the Energy and Finance sector. For the next steps, we could try and improve our information by scraping and getting all of the data in every company to illustrate and show the best picture for these sectors. This will be the improvement that we might need to do to see the wider picture of the market.

Overall, our analysis has shown the changes in stock prices, volume, market capitalization before and after the pandemic. The pandemic and its consequences on the economy make it difficult to predict which companies will thrive and succeed in the future. However, we hope that some of our findings will shed light on some information about the general market trends observed when dealing with a global pandemic.

Contribution for every member:

Duc: Together with Franco, I am in charge of scheduling our appointments, making sure everyone has created the best graph possible and finding the correct finance sources. Moreover, I tried my best to make sure our projects go on time and smoothly by setting up missions after every meeting as well as the overall goal for each section. I attended all the meetings and supported my teammates if needed. I created the moving graphs which shows the change in the rate of return for every company and every sector. With these graphs, I tried to see which company generates the highest return during the period and which sector performs the best during the pandemic.

Franco: I contributed to the project by sharing my knowledge on different finance concepts and the API sources that we could use. I also assembled the data so that it would be in a time series format and created the dummy variable for each sector. Also, I motivated my friends to focus on different areas ensuring that graphs wouldn’t be repetitive. I attended all the meetings and achieved all of the objectives the group set in a timely manner. I created the bar graphs showing the proportions of negative and positive returns, as well as the graph showing the monthly volume of different sectors. For the second graph I chose to work with plotly, a tool that we didn’t learn with much depth in class but that called my attention. I learned to use it and shared my newly acquired knowledge with the team.

Vichy: During the start of the project, along with other team members, I participated in finding a data set for the project and downloading and preparing the data for the graphing. I received help from my teammate in making all the data clean, consistent and ready for manipulation. I am responsible for creating partition graphs for market cap and trade return by sectors and companies. Consequently, I created three animated graph, one stacked bar chart for showing average return by sector over time, one treemap showing market cap partition by sector and one more treemap showing market cap partition by companies over time.

Max: I contributed to the group by combining the companies in the Energy, Real Estate, and xxx sectors together. I calculated the rate of return of these companies separately and found their average. Besides, I also calculated the First Day market Cap of these companies by market shares. Finally, I made a facet wrap animation graph of changing rate of return for different sectors (I take the average of three companies within the sector)

LS0tCnRpdGxlOiAiRmluYWwgUHJvamVjdCBEYXRhIFNjaWVuY2UiCmF1dGhvcjogIkR1YyBOZ28sIFZpY2hlYXJpdGggTWVhcywgRnJhbmNvIFNhbGluYXMsIE1heCBXYW5nIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgdG9jOiBUUlVFCiAgICB0b2NfZmxvYXQ6IFRSVUUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdGhlbWU6IGpvdXJuYWwKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBlcnJvcj1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSkKYGBgCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpICAgICAjIGZvciBkYXRhIGNsZWFuaW5nIGFuZCBwbG90dGluZwpsaWJyYXJ5KGx1YnJpZGF0ZSkgICAgICMgZm9yIGRhdGUgbWFuaXB1bGF0aW9uCmxpYnJhcnkob3BlbmludHJvKSAgICAgIyBmb3IgdGhlIGFiYnIyc3RhdGUoKSBmdW5jdGlvbgpsaWJyYXJ5KGdwbG90cykgICAgICAgICMgZm9yIGNvbDJoZXgoKSBmdW5jdGlvbgpsaWJyYXJ5KFJDb2xvckJyZXdlcikgICMgZm9yIGNvbG9yIHBhbGV0dGVzCmxpYnJhcnkoZ2d0aGVtZXMpICAgICAgIyBmb3IgbW9yZSB0aGVtZXMgKGluY2x1ZGluZyB0aGVtZV9tYXAoKSkKbGlicmFyeShwbG90bHkpICAgICAgICAjIGZvciB0aGUgZ2dwbG90bHkoKSAtIGJhc2ljIGludGVyYWN0aXZpdHkKbGlicmFyeShnZ2FuaW1hdGUpICAgICAjIGZvciBhZGRpbmcgYW5pbWF0aW9uIGxheWVycyB0byBnZ3Bsb3RzCmxpYnJhcnkodHJhbnNmb3JtcikgICAgIyBmb3IgInR3ZWVuaW5nIiAoZ2dhbmltYXRlKQpsaWJyYXJ5KGdpZnNraSkgICAgICAgICMgbmVlZCB0aGUgbGlicmFyeSBmb3IgY3JlYXRpbmcgZ2lmcyBidXQgZG9uJ3QgbmVlZCB0byBsb2FkIGVhY2ggdGltZQpsaWJyYXJ5KHNoaW55KSAgICAgICAgICMgZm9yIGNyZWF0aW5nIGludGVyYWN0aXZlIGFwcHMKbGlicmFyeShsdWJyaWRhdGUpICAgICAjIGZvciBkYXRlIG1hbmlwdWxhdGlvbgpsaWJyYXJ5KGdndGhlbWVzKSAgICAgICMgZm9yIGV2ZW4gbW9yZSBwbG90dGluZyB0aGVtZXMKbGlicmFyeShqYW5pdG9yKSAgCmxpYnJhcnkodHJlZW1hcGlmeSkKdGhlbWVfc2V0KHRoZW1lX21pbmltYWwoKSkKYGBgCgoKYGBge3IsIGVjaG89RkFMU0V9CiMjOiBIZXJlIGlzIHRoZSBpbmZvcm1hdGlvbiBhYm91dCBldmVyeSBjb21wYW55IHRoYXQgd2UgYXJlIGRvaW5nCkFBUEwgPC0gcmVhZF9jc3YoIkFBUEwuY3N2IikKQUFQTCA8LSBBQVBMJT4lIAogIHNlbGVjdCgtT3BlbiwgLUhpZ2gsIC1Mb3csIC1gQWRqIENsb3NlYCkgJT4lIAogIG11dGF0ZShTZWN0b3IgPSAiVGVjaG5vbG9neSIsCiAgICAgICAgIENvbXBhbnkgPSAiQUFQTCIpICU+JSAKICBtdXRhdGUocmV0dXJuID0gKENsb3NlIC0gNzUuMDg3NSkvIDc1LjA4NzUgKiAxMDApICU+JSAKICBtdXRhdGUoc2hhcmVzID0gMTcwMDE4MDIwMDApICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKSAKCkhPTiA8LSByZWFkX2NzdigiSE9OLmNzdiIpCkhPTiA8LSBIT04gJT4lIAogIHNlbGVjdCgtT3BlbiwgLUhpZ2gsIC1Mb3csIC1gQWRqIENsb3NlYCkgJT4lIAogIG11dGF0ZShTZWN0b3IgPSAiSW5kdXN0cmlhbHMiLAogICAgICAgICBDb21wYW55ID0gIkhPTiIpICU+JSAKICBtdXRhdGUocmV0dXJuID0gKENsb3NlIC0gMTgwLjc5KS8gMTgwLjc5ICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyAgPSA3ODQxMjIyODgpICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKSAKClVOUCA8LSByZWFkX2NzdigiVU5QLmNzdiIpClVOUCA8LSBVTlAgJT4lIAogIHNlbGVjdCgtT3BlbiwgLUhpZ2gsIC1Mb3csIC1gQWRqIENsb3NlYCkgJT4lIAogIG11dGF0ZShTZWN0b3IgPSAiSW5kdXN0cmlhbHMiLAogICAgICAgICBDb21wYW55ID0gIlVOUCIpICU+JSAKICBtdXRhdGUocmV0dXJuID0gKENsb3NlIC0gMTgyLjI3KS8gMTgyLjI3ICogMTAwKSAgJT4lIAogIG11dGF0ZShzaGFyZXMgID0gNzg0MTIyMjg4KSAlPiUgCiAgbXV0YXRlKG1hcmtldF9jYXAgPSBzaGFyZXMgKiBDbG9zZSkgCgpVUFMgPC0gcmVhZF9jc3YoIlVQUy5jc3YiKQpVUFMgPC0gVVBTICU+JSAKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JSAKICBtdXRhdGUoU2VjdG9yID0gIkluZHVzdHJpYWxzIiwKICAgICAgICAgQ29tcGFueSA9ICJVUFMiKSAlPiUgCiAgbXV0YXRlKHJldHVybiA9IChDbG9zZSAtIDExNi43OSkvIDExNi43OSAqIDEwMCkgJT4lIAogIG11dGF0ZShzaGFyZXMgID0gMTczMzYyOTA1KSAlPiUgCiAgbXV0YXRlKG1hcmtldF9jYXAgPSBzaGFyZXMgKiBDbG9zZSkgCgpKTkogPC0gcmVhZF9jc3YoIkpOSi5jc3YiKQpKTkogPC0gSk5KICU+JSAKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JSAKICBtdXRhdGUoU2VjdG9yID0gIkhlYWx0aCBjYXJlIiwKICAgICAgICAgQ29tcGFueSA9ICJKTkoiKSAlPiUgCiAgbXV0YXRlKHJldHVybiA9IChDbG9zZSAtIDE0NS45NykvIDE0NS45NyAqIDEwMCkgJT4lIAogIG11dGF0ZShzaGFyZXMgID0gMjY2MzEzODU3OSkgJT4lIAogIG11dGF0ZShtYXJrZXRfY2FwID0gc2hhcmVzICogQ2xvc2UpIAogIApVTkggPC0gcmVhZF9jc3YoIlVOSC5jc3YiKQpVTkggPC0gVU5IICU+JSAKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JSAKICBtdXRhdGUoU2VjdG9yID0gIkhlYWx0aCBjYXJlIiwKICAgICAgICAgQ29tcGFueSA9ICJVTkgiKSAlPiUgCiAgbXV0YXRlKHJldHVybiA9IChDbG9zZSAtIDI5Mi41MCkvIDI5Mi41MCAqIDEwMCkgJT4lIAogIG11dGF0ZShzaGFyZXMgID0gOTQ1MzE5NDA0KSAlPiUgCiAgbXV0YXRlKG1hcmtldF9jYXAgPSBzaGFyZXMgKiBDbG9zZSkKClJISEJZPC0gcmVhZF9jc3YoIlJISEJZLmNzdiIpClJISEJZIDwtIFJISEJZICU+JSAKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JSAKICBtdXRhdGUoU2VjdG9yID0gIkhlYWx0aCBjYXJlIiwKICAgICAgICAgQ29tcGFueSA9ICJSSEhCWSIpICU+JSAKICBtdXRhdGUocmV0dXJuID0gKENsb3NlIC0gNDAuODkpLyA0MC44OSAqIDEwMCkgJT4lIAogIG11dGF0ZShzaGFyZXMgPSAxNjAwMDAwMDApICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQogICAgCiAgCgpNU0ZUPC0gcmVhZF9jc3YoIk1TRlQuY3N2IikKTVNGVCA8LSBNU0ZUICU+JSAKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JSAKICBtdXRhdGUoU2VjdG9yID0gIlRlY2hub2xvZ3kiLAogICAgICAgICBDb21wYW55ID0gIk1TRlQiKSAlPiUgCiAgbXV0YXRlKHJldHVybiA9IChDbG9zZSAtIDE2MC42MgkpLyAxNjAuNjIJICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDc2MzU0MDk0MDApICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQogIAoKCk5WREE8LSByZWFkX2NzdigiTlZEQS5jc3YiKQpOVkRBIDwtIE5WREEgJT4lIAogIHNlbGVjdCgtT3BlbiwgLUhpZ2gsIC1Mb3csIC1gQWRqIENsb3NlYCkgJT4lIAogIG11dGF0ZShTZWN0b3IgPSAiVGVjaG5vbG9neSIsCiAgICAgICAgIENvbXBhbnkgPSAiTlZEQSIpICU+JSAKICBtdXRhdGUocmV0dXJuID0gKENsb3NlIC0gMjM5LjkxKS8gMjM5LjkxICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDYyMDAwMDAwMCkgJT4lIAogIG11dGF0ZShtYXJrZXRfY2FwID0gc2hhcmVzICogQ2xvc2UpCiAgCgoKR09PR0w8LSByZWFkX2NzdigiR09PR0wuY3N2IikKR09PR0wgPC0gR09PR0wgJT4lIAogIHNlbGVjdCgtT3BlbiwgLUhpZ2gsIC1Mb3csIC1gQWRqIENsb3NlYCkgJT4lIAogIG11dGF0ZShTZWN0b3IgPSAiQ29tbXVuaWNhdGlvbiBTZXJ2aWNlcyIsCiAgICAgICAgIENvbXBhbnkgPSAiR09PR0wiKSAlPiUgCiAgbXV0YXRlKHJldHVybiA9IChDbG9zZSAtIDEzNjguNjgJKS8gMTM2OC42OAkgKiAxMDApICU+JSAKICBtdXRhdGUoc2hhcmVzID0gMjk5MzYwMDI5KSAlPiUgCiAgbXV0YXRlKG1hcmtldF9jYXAgPSBzaGFyZXMgKiBDbG9zZSkKICAKClRDRUhZPC0gcmVhZF9jc3YoIlRDRUhZLmNzdiIpClRDRUhZIDwtIFRDRUhZICU+JSAKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JSAKICBtdXRhdGUoU2VjdG9yID0gIkNvbW11bmljYXRpb24gU2VydmljZXMiLAogICAgICAgICBDb21wYW55ID0gIlRDRUhZIikgJT4lIAogIG11dGF0ZShyZXR1cm4gPSAoQ2xvc2UgLSA0OS44OCkvIDQ5Ljg4ICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDcwNzg3NjY4KSAlPiUgCiAgbXV0YXRlKG1hcmtldF9jYXAgPSBzaGFyZXMgKiBDbG9zZSkKICAKCkZCPC0gcmVhZF9jc3YoIkZCLmNzdiIpCkZCIDwtIEZCICU+JSAKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JSAKICBtdXRhdGUoU2VjdG9yID0gIkNvbW11bmljYXRpb24gU2VydmljZXMiLAogICAgICAgICBDb21wYW55ID0gIkZCIikgJT4lIAogIG11dGF0ZShyZXR1cm4gPSAoQ2xvc2UgLSAyMDkuNzgpLyAyMDkuNzggKiAxMDApICU+JSAKICBtdXRhdGUoc2hhcmVzID0gMjQwNTQ0ODQxMCkgJT4lIAogIG11dGF0ZShtYXJrZXRfY2FwID0gc2hhcmVzICogQ2xvc2UpCiAgIAoKTkVFPC0gcmVhZF9jc3YoIk5FRS5jc3YiKQpORUUgPC0gTkVFICU+JSAKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JSAKICBtdXRhdGUoU2VjdG9yID0gIlV0aWxpdGllcyIsCiAgICAgICAgIENvbXBhbnkgPSAiTkVFIikgJT4lIAogIG11dGF0ZShyZXR1cm4gPSAoQ2xvc2UgLSA1OS42NTUwKS8gNTkuNjU1MCAqIDEwMCkgJT4lIAogIG11dGF0ZShzaGFyZXMgPSA0ODg5NjU4OTMpICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQogIAogIAoKRU5MQVk8LSByZWFkX2NzdigiRU5MQVkuY3N2IikKRU5MQVkgPC0gRU5MQVkgJT4lIAogIHNlbGVjdCgtT3BlbiwgLUhpZ2gsIC1Mb3csIC1gQWRqIENsb3NlYCkgJT4lIAogIG11dGF0ZShTZWN0b3IgPSAiVXRpbGl0aWVzIiwKICAgICAgICAgQ29tcGFueSA9ICJFTkxBWSIpICU+JSAKICBtdXRhdGUocmV0dXJuID0gKENsb3NlIC0gOC4wNSkvIDguMDUgKiAxMDApICAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDYxNzYxOTYyNzkpICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQogIAoKCklCRFNGPC0gcmVhZF9jc3YoIklCRFNGLmNzdiIpCklCRFNGIDwtIElCRFNGICU+JSAKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JSAKICBtdXRhdGUoU2VjdG9yID0gIlV0aWxpdGllcyIsCiAgICAgICAgIENvbXBhbnkgPSAiSUJEU0YiKSAlPiUgCiAgbXV0YXRlKHJldHVybiA9IChDbG9zZSAtIDEwLjIzKS8gMTAuMjMgKiAxMDApICU+JQogIG11dGF0ZShzaGFyZXMgPSA2MzYyMDAwMDAwKSAlPiUgCiAgbXV0YXRlKG1hcmtldF9jYXAgPSBzaGFyZXMgKiBDbG9zZSkKICAKICAKCkJSS0E8LSByZWFkX2NzdigiQlJLLUEuY3N2IikKQlJLQSA8LSBCUktBICU+JSAKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JSAKICBtdXRhdGUoU2VjdG9yID0gIkZpbmFuY2lhbHMiLAogICAgICAgICBDb21wYW55ID0gIkJSS0EiKSAlPiUgCiAgbXV0YXRlKHJldHVybiA9IChDbG9zZSAtIDM0MjI2MSkvIDM0MjI2MSAqIDEwMCkgJT4lIAogIG11dGF0ZShzaGFyZXMgPSAxMzM2MzQ4LjYwOSApICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQogIAoKSlBNPC0gcmVhZF9jc3YoIkpQTS5jc3YiKQpKUE0gPC0gSlBNICU+JSAKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JSAKICBtdXRhdGUoU2VjdG9yID0gIkZpbmFuY2lhbHMiLAogICAgICAgICBDb21wYW55ID0gIkpQTSIpICU+JSAKICBtdXRhdGUocmV0dXJuID0gKENsb3NlIC0gMTQxLjA5KS8gMTQxLjA5ICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDMwODQwMDAwMDApICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQogIAoKVjwtIHJlYWRfY3N2KCJWLmNzdiIpClYgPC0gViAlPiUgCiAgc2VsZWN0KC1PcGVuLCAtSGlnaCwgLUxvdywgLWBBZGogQ2xvc2VgKSAlPiUgCiAgbXV0YXRlKFNlY3RvciA9ICJGaW5hbmNpYWxzIiwKICAgICAgICAgQ29tcGFueSA9ICJWIikgJT4lIAogIG11dGF0ZShyZXR1cm4gPSAoQ2xvc2UgLSAxOTEuMTIpLyAxOTEuMTIgKiAxMDApICAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDE2OTYxMTM2MDMpICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQogIAoKQU1aTjwtIHJlYWRfY3N2KCJBTVpOLmNzdiIpCkFNWk4gPC0gQU1aTiAlPiUgCiAgc2VsZWN0KC1PcGVuLCAtSGlnaCwgLUxvdywgLWBBZGogQ2xvc2VgKSAlPiUgCiAgbXV0YXRlKFNlY3RvciA9ICJDb21tdW5pY2F0aW9uIERpc2NyZXRpb25hcnkiLAogICAgICAgICBDb21wYW55ID0gIkFNWk4iKSAlPiUgCiAgbXV0YXRlKHJldHVybiA9IChDbG9zZSAtIDE4OTguMDEpLyAxODk4LjAxICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDUwMzU2NDc0MykgJT4lIAogIG11dGF0ZShtYXJrZXRfY2FwID0gc2hhcmVzICogQ2xvc2UpCiAgCgpUU0xBPC0gcmVhZF9jc3YoIlRTTEEuY3N2IikKVFNMQSA8LSBUU0xBICU+JSAKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JSAKICBtdXRhdGUoU2VjdG9yID0gIkNvbW11bmljYXRpb24gRGlzY3JldGlvbmFyeSIsCiAgICAgICAgIENvbXBhbnkgPSAiVFNMQSIpICU+JSAKICBtdXRhdGUocmV0dXJuID0gKENsb3NlIC0gODYuMDUyKS8gODYuMDUyICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDE4MTM0MTU4NikgJT4lIAogIG11dGF0ZShtYXJrZXRfY2FwID0gc2hhcmVzICogQ2xvc2UpCiAgCgoKQkFCQTwtIHJlYWRfY3N2KCJCQUJBLmNzdiIpCkJBQkEgPC0gQkFCQSAlPiUgCiAgc2VsZWN0KC1PcGVuLCAtSGlnaCwgLUxvdywgLWBBZGogQ2xvc2VgKSAlPiUgCiAgbXV0YXRlKFNlY3RvciA9ICJDb21tdW5pY2F0aW9uIERpc2NyZXRpb25hcnkiLAogICAgICAgICBDb21wYW55ID0gIkJBQkEiKSAlPiUgCiAgbXV0YXRlKHJldHVybiA9IChDbG9zZSAtIDIxOS43NwkpLyAyMTkuNzcJICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDIxNjg4OTQ4OCkgJT4lIAogIG11dGF0ZShtYXJrZXRfY2FwID0gc2hhcmVzICogQ2xvc2UpCiAgCgoKV01UPC0gcmVhZF9jc3YoIldNVC5jc3YiKQpXTVQgPC0gV01UICU+JSAKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JSAKICBtdXRhdGUoU2VjdG9yID0gIkNvbnN1bWVyIFN0YXBsZXMiLAogICAgICAgICBDb21wYW55ID0gIldNVCIpICU+JSAKICBtdXRhdGUocmV0dXJuID0gKENsb3NlIC0gMTE4Ljk0KS8gMTE4Ljk0ICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDI4Njk2ODQyMzApICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQogIAoKTlNSR0Y8LSByZWFkX2NzdigiTlNSR0YuY3N2IikKTlNSR0YgPC0gTlNSR0YgJT4lIAogIHNlbGVjdCgtT3BlbiwgLUhpZ2gsIC1Mb3csIC1gQWRqIENsb3NlYCkgJT4lIAogIG11dGF0ZShTZWN0b3IgPSAiQ29uc3VtZXIgU3RhcGxlcyIsCiAgICAgICAgIENvbXBhbnkgPSAiTlNSR0YiKSAlPiUgCiAgbXV0YXRlKHJldHVybiA9IChDbG9zZSAtIDEwOC4wNgkpLyAxMDguMDYJICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDI5MjkwMDAwMDApICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQogIAoKUEc8LSByZWFkX2NzdigiUEcuY3N2IikKUEcgPC0gUEcgJT4lIAogIHNlbGVjdCgtT3BlbiwgLUhpZ2gsIC1Mb3csIC1gQWRqIENsb3NlYCkgJT4lIAogIG11dGF0ZShTZWN0b3IgPSAiQ29uc3VtZXIgU3RhcGxlcyIsCiAgICAgICAgIENvbXBhbnkgPSAiUEciKSAlPiUgCiAgbXV0YXRlKHJldHVybiA9IChDbG9zZSAtIDEyMy40MQkpLyAxMjMuNDEJICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDI1MDIyNTk2NjgpICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQogIApTUFk8LSByZWFkX2NzdigiU1BZLmNzdiIpClNQWSA8LSBTUFkgJT4lIAogIHNlbGVjdCgtT3BlbiwgLUhpZ2gsIC1Mb3csIC1gQWRqIENsb3NlYCkgJT4lIAogIG11dGF0ZShTZWN0b3IgPSAiQWxsIGZpZWxkIiwKICAgICAgICAgQ29tcGFueSA9ICJTUFkiKSAlPiUgCiAgbXV0YXRlKHJldHVybiA9IChDbG9zZSAtIDMyNC44NwkpLyAzMjQuODcJICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDEzMDEyNDUwKSAlPiUgCiAgbXV0YXRlKG1hcmtldF9jYXAgPSBzaGFyZXMgKiBDbG9zZSkKYGBgCgpgYGB7cn0KWE9NIDwtIHJlYWRfY3N2KCJYT00uY3N2IikKWE9NIDwtIFhPTSAlPiUKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JSAKICBtdXRhdGUoU2VjdG9yPSJFbmVyZ3kiLAogICAgICAgICBDb21wYW55PSAiWE9NIikgJT4lIAogICBtdXRhdGUocmV0dXJuID0gKENsb3NlIC0gNzAuOTApLyA3MC45MCAqIDEwMCkgJT4lIAogIG11dGF0ZShzaGFyZXMgPSA0MzQxNjc5NDQpICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQoKCgpDVlggPC0gcmVhZF9jc3YoIkNWWC5jc3YiKQpDVlggPC0gQ1ZYICU+JQogIHNlbGVjdCgtT3BlbiwgLUhpZ2gsIC1Mb3csIC1gQWRqIENsb3NlYCkgJT4lCiAgbXV0YXRlKFNlY3Rvcj0iRW5lcmd5IiwKICAgICAgICAgQ29tcGFueT0gIkNWWCIpICU+JQogICBtdXRhdGUocmV0dXJuID0gKENsb3NlIC0gMTIxLjQzKS8gMTIxLjQzICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDE5NzAyMzkyMykgJT4lIAogIG11dGF0ZShtYXJrZXRfY2FwID0gc2hhcmVzICogQ2xvc2UpCiAgCgpSRFNfQSA8LXJlYWRfY3N2KCJSRFMtQS5jc3YiKQpSRFNfQSA8LSBSRFNfQSAlPiUKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JQogIG11dGF0ZShTZWN0b3I9IkVuZXJneSIsCiAgICAgICAgIENvbXBhbnk9ICJSRFNfQSIpJT4lCiAgIG11dGF0ZShyZXR1cm4gPSAoQ2xvc2UgLSA1OS43NCkvIDU5Ljc0ICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDgwNTgzMDAwMDApICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQogIAoKZW5lcmd5IDwtIHJiaW5kKFhPTSxDVlgsUkRTX0EpCmBgYAoKYGBge3J9CkFNVCA8LSByZWFkX2NzdigiQU1ULmNzdiIpCkFNVCA8LSBBTVQgJT4lCiAgc2VsZWN0KC1PcGVuLCAtSGlnaCwgLUxvdywgLWBBZGogQ2xvc2VgKSAlPiUKICBtdXRhdGUoU2VjdG9yPSJSZWFsIEVzdGF0ZSIsCiAgICAgICAgIENvbXBhbnk9ICJBTVQiKSU+JQogIG11dGF0ZShyZXR1cm4gPSAoQ2xvc2UgLSAyMjguNTApLyAyMjguNTAgKiAxMDApICU+JSAKICBtdXRhdGUoc2hhcmVzID0gNDYwMTQ0NTcpICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQogIApLRSA8LSByZWFkX2NzdigiS0UuY3N2IikKS0UgPC0gS0UgJT4lCiAgc2VsZWN0KC1PcGVuLCAtSGlnaCwgLUxvdywgLWBBZGogQ2xvc2VgKSAlPiUKICBtdXRhdGUoU2VjdG9yPSJSZWFsIEVzdGF0ZSIsCiAgICAgICAgIENvbXBhbnk9ICJLRSIpJT4lCiAgbXV0YXRlKHJldHVybiA9IChDbG9zZSAtIDE3LjY5MCkvIDE3LjY5MCAqIDEwMCkgJT4lIAogIG11dGF0ZShzaGFyZXMgPSAyNDkyMzk3OTAwKSAlPiUgCiAgbXV0YXRlKG1hcmtldF9jYXAgPSBzaGFyZXMgKiBDbG9zZSkKICAKClBMRCA8LSByZWFkX2NzdigiUExELmNzdiIpClBMRCA8LSBQTEQgJT4lCiAgc2VsZWN0KC1PcGVuLCAtSGlnaCwgLUxvdywgLWBBZGogQ2xvc2VgKSAlPiUKICBtdXRhdGUoU2VjdG9yPSJSZWFsIEVzdGF0ZSIsCiAgICAgICAgIENvbXBhbnk9ICJQTEQiKSU+JQogIG11dGF0ZShyZXR1cm4gPSAoQ2xvc2UgLSA4OC40MAkpLyA4OC40MCAqIDEwMCkgJT4lIAogIG11dGF0ZShzaGFyZXMgPSA3Mzk1MDAwMDApICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQogCnJlYWxfZXN0YXRlIDwtIHJiaW5kKEFNVCxLRSxQTEQpCmBgYAoKYGBge3J9CkJIUCA8LXJlYWRfY3N2KCJCSFAuY3N2IikKQkhQIDwtIEJIUCU+JQogIHNlbGVjdCgtT3BlbiwgLUhpZ2gsIC1Mb3csIC1gQWRqIENsb3NlYCkgJT4lCiAgbXV0YXRlKFNlY3Rvcj0iTWF0ZXJpYWwiLAogICAgICAgICBDb21wYW55PSAiUkRTX0EiKSAlPiUKICBtdXRhdGUocmV0dXJuID0gKENsb3NlIC0gNTQuOTIpLyA1NC45MiAqIDEwMCkgJT4lIAogIG11dGF0ZShzaGFyZXMgPSAyNDg0MjEwNTMpICU+JSAKICBtdXRhdGUobWFya2V0X2NhcCA9IHNoYXJlcyAqIENsb3NlKQogIApMSU4gPC1yZWFkX2NzdigiTElOLmNzdiIpCkxJTiA8LSBMSU4gJT4lCiAgc2VsZWN0KC1PcGVuLCAtSGlnaCwgLUxvdywgLWBBZGogQ2xvc2VgKSAlPiUKICBtdXRhdGUoU2VjdG9yPSJNYXRlcmlhbCIsCiAgICAgICAgIENvbXBhbnk9ICJMSU4iKSAlPiUKICBtdXRhdGUocmV0dXJuID0gKENsb3NlIC0gMjEwLjc0KS8gMjEwLjc0ICogMTAwKSAlPiUgCiAgbXV0YXRlKHNoYXJlcyA9IDUyOTE1MjkyKSAlPiUgCiAgbXV0YXRlKG1hcmtldF9jYXAgPSBzaGFyZXMgKiBDbG9zZSkKClJJTyA8LXJlYWRfY3N2KCJSSU8uY3N2IikKUklPIDwtIFJJTyAlPiUKICBzZWxlY3QoLU9wZW4sIC1IaWdoLCAtTG93LCAtYEFkaiBDbG9zZWApICU+JQogIG11dGF0ZShTZWN0b3I9Ik1hdGVyaWFsIiwKICAgICAgICAgQ29tcGFueT0gIlJJTyIpJT4lCiAgbXV0YXRlKHJldHVybiA9IChDbG9zZSAtIDU5Ljg5KS8gNTkuODkgKiAxMDApICU+JSAKICBtdXRhdGUoc2hhcmVzID0gMTcwMDc3NDI3KSAlPiUgCiAgbXV0YXRlKG1hcmtldF9jYXAgPSBzaGFyZXMgKiBDbG9zZSkKICAKbWF0ZXJpYWwgPC0gcmJpbmQoQkhQLExJTixSSU8pCmBgYAoKYGBge3J9CmNvbW11bmljYXRpb25fc2VydmljZXMgPC0gcmJpbmQoR09PR0wsIFRDRUhZLCBGQikKdXRpbGl0aWVzIDwtIHJiaW5kKE5FRSwgRU5MQVksIElCRFNGKQpmaW5hbmNpYWxzIDwtIHJiaW5kKEpQTSwgQlJLQSwgVikKY29tbXVuaWNhdGlvbl9kaXNjcmV0aW9uYXJ5IDwtIHJiaW5kKEFNWk4sIFRTTEEsIEJBQkEpCmNvbnN1bWVyX3N0YXBsZSA8LSByYmluZChXTVQsIE5TUkdGLCBQRykKYGBgCgpgYGB7cn0KdGVjaCA8LSByYmluZChBQVBMLE1TRlQsTlZEQSkKaW5kdXN0cmlhbHMgPC0gcmJpbmQoSE9OLFVOUCxVUFMpCmhlYWx0aCA8LSByYmluZChKTkosVU5ILFJISEJZKQpgYGAKCmBgYHtyfQpzcCA8LSByYmluZChjb21tdW5pY2F0aW9uX3NlcnZpY2VzLCB1dGlsaXRpZXMsIGZpbmFuY2lhbHMsIGNvbW11bmljYXRpb25fZGlzY3JldGlvbmFyeSwgY29uc3VtZXJfc3RhcGxlLAogICAgICAgICAgICB0ZWNoLCBpbmR1c3RyaWFscywgaGVhbHRoLCByZWFsX2VzdGF0ZSwgbWF0ZXJpYWwsIGVuZXJneSwgU1BZKQpgYGAKCgoKIyBJbnRyb2R1Y3Rpb246IApXZSBoYXZlIHNlZW4gbXVsdGlwbGUgY2hhbmdlcyBhcm91bmQgdGhlIHdvcmxkIGFmdGVyIG9uZSB5ZWFyLiBUaGUgbWFpbiByZWFzb24gZm9yIHRoYXQgaXMgYmVjYXVzZSBvZiB0aGUgY29yb25hdmlydXMgcGFuZGVtaWMuIEZpcnN0bHkgdGhvdWdodCBvZiBhcyBhIGNvbW1vbiBmbHUgaW4gV3VoYW4sIENoaW5hLCB0aGUgcGFuZGVtaWMgaGFzIHNwcmVhZCBhcm91bmQgdGhlIHdvcmxkLCB3aXRoIG1vcmUgdGhhbiAxMDAgbWlsbGlvbiBjYXNlcyBhbmQgbW9yZSB0aGFuIDIuNSBtaWxsaW9uIGRlYXRocy4gRXNwZWNpYWxseSBpbiB0aGUgVVMsIHdlIGhhdmUgc2VlbiBhcm91bmQgMzAgbWlsbGlvbiBjYXNlcyB3aXRoIG1vcmUgdGhhbiA1MDAsMDAwIGRlYXRocyByZXN1bHRpbmcgZnJvbSB0aGUgcGFuZGVtaWMgKGFjY29yZGluZyB0byBXb3JsZG9tZXRlcikgLiBDb3JvbmF2aXJ1cyBoYXMgY2hhbmdlZCBvdXIgcGVyc3BlY3RpdmUgaW4gbXVsdGlwbGUgYXJlYXMsIGhvd2V2ZXIsIGluIHRoaXMgYmxvZyBwb3N0LCB3ZSBmb2N1cyBzcGVjaWZpY2FsbHkgb24gaXRzIGltcGFjdCBvbiBjb21wYW5pZXMgYW5kIHNlY3RvcnMgaW4gdGhlIFVTIHN0b2NrIG1hcmtldC4gV2Ugd2lsbCBzZWUgd2hhdCBhcmUgdGhlIGNoYW5nZXMgaW4gc3RvY2sgcHJpY2UsIGluIG1hcmtldCBjYXBpdGFsaXphdGlvbiBhcyB3ZWxsIGFzIGhvdyBlYWNoIHNlY3RvciBoYXMgY2hhbmdlZCBhZnRlciB0aGUgcGFuZGVtaWMuIAoKRmlyc3QsIGFzIHdlIGhhdmUgbW9yZSB0aGFuIDIsODAwIGNvbXBhbmllcyB0cmFkaW5nIGluIHRoZSBOZXcgWW9yayBTdG9jayBFeGNoYW5nZSAoTllTRSksIGl0IGlzIHJlYWxseSBkaWZmaWN1bHQgdG8gZG8gaXQgaW4gYSBzaG9ydCBwZXJpb2Qgb2YgdGltZS4gSW5zdGVhZCwgd2UgdXNlZCB0aGUgd2Vic2l0ZSBZYWhvbyBGaW5hbmNlIHRvIGZpbmQgdGhlIGRhdGEgZm9yIHRoZSAzIGNvbXBhbmllcyB3aXRoIGhpZ2hlc3QgbWFya2V0IGNhcCBpbiBkaWZmZXJlbnQgMTEgc2VjdG9yczogQ29tbXVuaWNhdGlvbiBEaXNjcmV0aW9uYXJ5LCBDb21tdW5pY2F0aW9uIFNlcnZpY2VzLCBDb25zdW1lciBTdGFwbGVzLCBFbmVyZ3ksIEZpbmFuY2lhbHMsIEhlYWx0aCBDYXJlLCBJbmR1c3RyaWFscywgTWF0ZXJpYWwsIFJlYWwgRXN0YXRlLCBUZWNobm9sb2d5LCBVdGlsaXRpZXMuIFRoZW4sICB0byBjb21wYXJlIHRoZSByZXN1bHRzIGZyb20gZGlmZmVyZW50IHNlY3RvcnMgdG8gdGhlIHdpZGVyIG1hcmtldCwgd2UgdXNlZCB0aGUgU1BZLCB3aGljaCBpcyBhbiBFVEYgZm9yIHRoZSBTJlAgNTAwIHRoYXQgdHJhY2tzIHRoZSBjaGFuZ2VzIGluIHRoZSB2YWx1ZSBvZiB0aGUgYmlnZ2VzdCA1MDAgY29tcGFuaWVzIGluIHRoZSBtYXJrZXQuIFdlIGNsYXNzaWZpZWQgdGhlIFNQWSBkYXRhIGFzICDigJxBbGwgZmllbGRz4oCdLiBXZSB0cmFja2VkIHRoZSBkYXRhIGZyb20gMjAyMC0wMS0wMiB0byAyMDIxLTAzLTA0LCB1c2luZyB0aGUgdm9sdW1lIGFuZCB0aGUgY2xvc2luZyBwcmljZS4gV2UgYXNzZW1ibGVkIHRoZSBkYXRhIGluIGEgdGltZSBzZXJpZXMgZm9ybWF0IGNyZWF0aW5nIGR1bW15IHZhcmlhYmxlcyBmb3IgZWFjaCBzZWN0b3IsIHRoZW4gd2UgY2hvc2UgdG8gdXNlIHRoZSBjbG9zaW5nIHByaWNlIGdpdmVuIHRoYXQgaXQgc2hvd3MgdGhlIGZpbmFsIHZhbHVlIHRoYXQgbWFya2V0IHBhcnRpY2lwYW50cyBhdHRyaWJ1dGUgdG8gYSBzaGFyZSBhZnRlciB0cmFkaW5nLCBwcm92aWRpbmcgYSBtb3JlIHJlYWxpc3RpYyBkZXBpY3Rpb24gb2YgaXRzIHZhbHVlLiBUaGVuLCB3ZSBjYWxjdWxhdGVkIHRoZSBDdW11bGF0aXZlIFJhdGUgb2YgUmV0dXJuIGV2ZXJ5ZGF5IGJ5IHVzaW5nIHRoZSBmb2xsb3dpbmcgZm9ybXVsYTogCiAgCiQkCnJldHVybiA9IFxmcmFje1ByaWNlX2kgLSBQcmljZV8xfXtQcmljZV8xICogMTAwfQokJAoKV2UgYWxzbyBvYnRhaW5lZCB0aGUgbWFya2V0IGNhcCBieSBtdWx0aXBseWluZyB0aGUgbnVtYmVyIG9mIG1hcmtldCBzaGFyZXMgb2YgZWFjaCBjb21wYW55IGJ5IHRoZSBDbG9zaW5nIHByaWNlIGVhY2ggZGF5LiBXZSByZXRyaWV2ZWQgdGhlIG51bWJlciBvZiBzaGFyZXMgZnJvbSB0aGUgU0VDIGZpbGluZyB3ZWJzaXRlLgoKQWZ0ZXIgd2UgaGF2ZSBmb3VuZCB0aGUgd2F5IHRvIGNvbmR1Y3QgcmVzZWFyY2ggd2l0aCBvdXIgZGF0YSwgd2UgaGF2ZSBjcmVhdGVkIHRocmVlIG1haW4gcXVlc3Rpb25zOiAKICAgIAogICAgYS4gV2hpY2ggY29tcGFuaWVzIGFuZCB3aGljaCBzZWN0b3JzIGhhdmUgcGVyZm9ybWVkIHRoZSBiZXN0IGR1cmluZyB0aGUgcGVyaW9kPyBXaGF0IGlzIHRoZSBwcm9wb3J0aW9uIG9mIG5lZ2F0aXZlIGFuZCBwb3NpdGl2ZSBkYWlseSBhdmVyYWdlIHJldHVybiBmb3IgZWFjaCBzZWN0b3I/CiAgICBiLiBXaGF0IGFyZSB0aGUgY2hhbmdlcyBpbiBtYXJrZXQgY2FwaXRhbGl6YXRpb24/CiAgICBjLiBXaGljaCBjb21wYW5pZXMgaGF2ZSB0aGUgaGlnaGVzdCB0cmFkaW5nIHZvbHVtZT8gV2hpY2ggc2VjdG9ycyBoYXZlIHRoZSBoaWdoZXN0IG51bWJlciBvZiB0cmFkaW5nPwoKIyMgIFRoZSBwZXJmb3JtYW5jZSBvZiBjb21wYW5pZXMgYW5kIHRoZSBzZWN0b3JzOiAKCiMjIyBSZXR1cm4gYnkgc2VjdG9yczogCmBgYHtyLCBldmFsID0gRkFMU0V9CkEgPC0gc3AgJT4lCiAgZ3JvdXBfYnkoU2VjdG9yLERhdGUpJT4lCiAgc3VtbWFyaXNlKHJldHVybj1tZWFuKHJldHVybikpJT4lCiAgZ2dwbG90KGFlcyh5PXJldHVybix4PURhdGUsIGNvbG9yPVNlY3RvcikpKwogIGdlb21fbGluZSgpKwogIGxhYnMoeT0iIiwKICAgICAgIHg9IiIsCiAgICAgICBzdWJ0aXRsZSA9ICJEYXRlOiB7ZnJhbWVfYWxvbmd9IiwKICAgICAgIHRpdGxlID0gIkNoYW5naW5nIFJhdGUgb2YgUmV0dXJuIGZvciBEaWZmZXJlbnQgU2VjdG9ycyIpKwogIGZhY2V0X3dyYXAoflNlY3RvcixzY2FsZXM9ImZyZWVfeSIpKwogIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIleS0lbSIpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IDAsYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSsKICB0cmFuc2l0aW9uX3JldmVhbChEYXRlKQogIGFuaW1hdGUoQSx3aWR0aD02MDAsaGVpZ2h0PTQwMCkKCmFuaW1fc2F2ZSgiQWxsX0xpbmUuZ2lmIikKYGBgCgpgYGB7ciwgZWNobz0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJBbGxfTGluZS5naWYiKQpgYGAKCmBgYHtyLCBldmFsPUZBTFNFfQptb3ZpbmdfcmV0dXJuX3NlY3RvciA8LSBkcm9wX25hKHNwKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZSwgU2VjdG9yKSAlPiUgCiAgc3VtbWFyaXNlKHJldHVybiA9IG1lYW4ocmV0dXJuKSAvIDEwMCkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZSkgJT4lIAogICNzdW1tYXJpc2UoZGFpbHlfcmV0dXJuID0gc3VtKHJldHVybikpICU+JSAKICAjbXV0YXRlKHRvdGFsX3JldHVybl9wZXJpb2QgPSBjdW1zdW0oZGFpbHlfcmV0dXJuKSkgJT4lIAogIHRvcF9uKG4gPSAxMCwgd3QgPSByZXR1cm4pICU+JSAgCiAgYXJyYW5nZShEYXRlLCByZXR1cm4pICU+JSAKICBtdXRhdGUocmFuayA9IDE6IG4oKSkgJT4lIAogIGdncGxvdChhZXMoeSA9IGZhY3RvcihyYW5rKSwgeCA9IHJldHVybiwKICAgICAgICAgICAgIGZpbGwgPSByZXR1cm4pKSArIAogIGdlb21fY29sKCkgKyAKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gU2VjdG9yKSwKICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBoanVzdCA9ICJsZWZ0IiwgeCA9IDApICsKICBsYWJzKHRpdGxlID0gIkNoYW5nZSBpbiByYXRlIG9mIHJldHVybiBpbiBkaWZmZXJlbnQgc2VjdG9ycyIsCiAgICAgICBzdWJ0aXRsZSA9ICJEYXRlOiB7ZnJhbWVfdGltZX0iLAogICAgICAgeCA9ICIiLAogICAgICAgeSA9ICIiKSArCiAgdGhlbWUoYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSAgKwogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKCkgKyAKICB0cmFuc2l0aW9uX3RpbWUoRGF0ZSkgCgphbmltYXRlKG1vdmluZ19yZXR1cm5fc2VjdG9yLCBuZnJhbWVzID0gMjAwLCBkdXJhdGlvbiA9IDQ1KQphbmltX3NhdmUoIm1vdmluZ19yZXR1cm5fc2VjdG9yLmdpZiIpCmBgYAoKCgpgYGB7ciwgZWNobz0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJtb3ZpbmdfcmV0dXJuX3NlY3Rvci5naWYiKQpgYGAKCk92ZXJhbGwsIGl0IHNlZW1zIHRoYXQgdGhlIHJldHVybiBmb3IgdGhlIENvbW11bmljYXRpb24gRGlzY3JldGlvbmFyeSBpcyBjb25zaXN0ZW50bHkgZ3Jvd2luZywgYWxtb3N0IGluIGEgcG9zaXRpdmVseSBsaW5lYXIgd2F5LiBUaGUgbG93ZXN0IHJldHVybiBpcyBzdGlsbCBub3QgYmVsb3cgMC4gQ2hhbmdlcyBpbiByZXR1cm4gb2YgQ29tbXVuaWNhdGlvbiBTZXJ2aWNlcyBhbmQgVGVjaG5vbG9neSBmb2xsb3cgYSBzaW1pbGFyIHRyZW5kIHRvIHRoYXQgb2YgQ29tbXVuaWNhdGlvbiBEaXNjcmV0aW9uYXJ5IGluIHNoYXBlLCBidXQgaGF2ZSBhIHNtYWxsZXIgbWFnbml0dWRlICgtMjB+IDYwIGZvciBDUywgLTI1fjEwMCBmb3IgVCwgY29tcGFyZWQgdG8gMH4zMDAgZm9yIENEKS4gQ29uc3VtZXIgU3RhcGxlcyBmbHVjdHVhdGVkIG1pbGRseSwgZmFsbGluZyBzaGFycGx5IGZpcnN0IHRvIC0xMCBhbmQgcmVib3VuZGluZyBxdWlja2x5LCB0aGVuIGdyb3dpbmcgc3RlYWRpbHkgdG8gZmluYWxseSBkZWNyZWFzZSBiYWNrIHRvIDAgcmV0dXJuLgogICAgVGhlIHNpdHVhdGlvbiBmb3IgdGhlIEVuZXJneSBhbmQgRmluYW5jaWFscyBzZWN0b3JzIGlzIHRoZSB3b3JzdC4gU2luY2UgdGhlIGZpcnN0IGRheSwgRW5lcmd5J3MgY3VtdWxhdGl2ZSByZXR1cm4gaXMgbmVnYXRpdmUuIE9ubHkgdGhlIGxhc3QgbW9udGggaXMgcG9zaXRpdmUgZm9yIHRoZSBGaW5hbmNpYWxzIHNlY3Rvci4gSGVhbHRoIENhcmUsIEluZHVzdHJpYWxzLCBNYXRlcmlhbCwgUmVhbCBFc3RhdGUsIGFuZCBVdGlsaXRpZXMgZm9sbG93ZWQgYSBzaW1pbGFyIHRyZW5kLCBidXQgdGhlc2Ugc2VjdG9ycycgY29uZGl0aW9ucyBhcmUgYmV0dGVyIHRoYW4gdGhhdCBvZiBFbmVyZ3kgYW5kIEZpbmFuY2lhbHMuIEhlYWx0aCBDYXJlLCBJbmR1c3RyaWFscywgTWF0ZXJpYWwsIFJlYWwgRXN0YXRlLCBhbmQgVXRpbGl0aWVzIGhhdmUgc2ltaWxhciB0cmVuZHMgY29tcGFyZWQgdG8gdGhlIG92ZXJhbGwgbWFya2V0LgogICAgSW4gZ2VuZXJhbCwgdGhlIHJldHVybiBzaGFycGx5IGRyb3BwZWQgZnJvbSAyMDIwLTEtMSB0byBBcHJpbCAyMDIwIGFuZCB0aGVuIHJlYm91bmRlZCBhdCBhICBsb3dlciByYXRlLCBiYWNrIHRvIDAgaW4gQXVndXN0IDIwMjAuIEFmdGVyLCBpdCBvc2NpbGxhdGVkIHVwIGFuZCBkb3duIHVudGlsIDIwMjAgTm92ZW1iZXIgYW5kIHRoZW4gY29udGludW91c2x5IGluY3JlYXNlZCBzbG93bHkuIFNvIGZhciwgcmV0dXJuIGFzIGEgd2hvbGUgaXMgMjAlLgogICAgCmBgYHtyLCBmaWcud2lkdGg9IDEwLCBmaWcuaGVpZ2h0PSA0fQpyZXR1cm5fdHlwZSA8LSBzcCAlPiUgCiAgZmlsdGVyKFNlY3RvciE9IkFsbCBmaWVsZCIpICU+JSAKICBzZWxlY3QoLUNsb3NlLCAtVm9sdW1lKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZSwgU2VjdG9yKSAlPiUgCiAgbXV0YXRlKGF2Z19yZXR1cm4gPSBtZWFuKHJldHVybiksCiAgICAgICAgIHR5cGVfcmV0dXJuID0gaWZlbHNlKGF2Z19yZXR1cm48MCwgIm5lZ2F0aXZlIiwgInBvc2l0aXZlIikpJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgZ3JvdXBfYnkoU2VjdG9yKSAlPiUgCiAgbXV0YXRlKGBQcm9wb3J0aW9uIG5lZ2F0aXZlYCA9IG1lYW4odHlwZV9yZXR1cm4gPT0gIm5lZ2F0aXZlIiksCiAgICAgICAgIGBQcm9wb3J0aW9uIHBvc2l0aXZlYCA9IG1lYW4odHlwZV9yZXR1cm4gPT0gInBvc2l0aXZlIikpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGBQcm9wb3J0aW9uIG5lZ2F0aXZlYDpgUHJvcG9ydGlvbiBwb3NpdGl2ZWAsCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInByb3BfdHlwZSIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJwcm9wIikgJT4lIAogIHN1bW1hcml6ZShTZWN0b3IsIHByb3BfdHlwZSwgcHJvcCkgJT4lCiAgZGlzdGluY3QoU2VjdG9yLCBwcm9wX3R5cGUsIHByb3ApCgoKcmV0dXJuX3R5cGUgJT4lIAogIGdncGxvdChhZXMoeCA9IHByb3AsIHkgPSBwcm9wX3R5cGUsIGZpbGwgPSBwcm9wX3R5cGUgKSkgKyAKICBnZW9tX2NvbCgpKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChwcm9wLGRpZ2l0cyA9IDIpKSwgc2l6ZSA9IDIpKwogIGZhY2V0X3dyYXAoflNlY3RvcikrCiAgbGFicyh0aXRsZSA9ICJQcm9wb3J0aW9ucyBvZiBuZWdhdGl2ZSBhbmQgcG9zaXRpdmUgZGFpbHkgYXZlcmFnZSByZXR1cm5zIHBlciBzZWN0b3IiLAogICAgICAgZmlsbCA9ICJUeXBlIG9mIHJldHVybiIsCiAgICAgICB4ID0gIiIsIAogICAgICAgeSA9ICIiKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAwLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yLnk9ZWxlbWVudF9ibGFuaygpKQogIApgYGAKCkFkZGl0aW9uYWxseSwgd2UgdHJ5IHRvIHNlZSB0aGUgcHJvcG9ydGlvbiBvZiB0aW1lIGluIHdoaWNoIHRoZSBhdmVyYWdlIG9mIHRoZSBjdW11bGF0aXZlIHJldHVybiBvZiB0aGUgYmVzdCBzdG9ja3MgcGVyIHNlY3RvciBoYXZlIGJlZW4gb3ZlciBvciB1bmRlciB0aGUgYmFzZSBwcmljZS4gSW4gaGVyZSwgaXQgY29tZXMgYXMgbm8gc3VycHJpc2UgYXMgQ29tbXVuaWNhdGlvbiBEaXNjcmV0aW9uYXJ5IHdhcyB0aGUgc2VjdG9yIHdpdGggdGhlIGhpZ2hlc3QgcHJvcG9ydGlvbiBvZiBwb3NpdGl2ZSByZXR1cm5zIHJlbGF0aXZlIHRvIHRoZSBuZWdhdGl2ZSByZXR1cm5zLiBUaGlzIG1lYW5pbmcsIHRoYXQgOTclIG9mIHRoZSB0aW1lIHRoZSBDb21tdW5pY2F0aW9uIERpc2NyZXRpb25hcnkgc2VjdG9yIGhhZCBwb3NpdGl2ZSByZXR1cm5zIHJlbGF0aXZlIHRvIHRoZSBpbml0aWFsIHByaWNlLiBIYWQgYSBwZXJzb24gYm91Z2h0IHNoYXJlcyBvZiB0aGUgY29tcGFuaWVzIGluIHRoaXMgc2VjdG9yIG9uIEphbnVhcnkgMm5kLCB0aGV5IHdvdWxkIGhhdmUgc2xlcHQgcGVhY2VmdWxseSA5NyUgb2YgdGhlIHRpbWUuIE9uIHRoZSBvdGhlciBoYW5kLCB0aGUgRW5lcmd5IHNlY3RvciB3YXMgdGhlIHNlY3RvciB3aXRoIHRoZSBoaWdoZXN0IHByb3BvcnRpb24gb2YgbmVnYXRpdmUgcmV0dXJucyByZWxhdGl2ZSB0byBwb3NpdGl2ZSByZXR1cm5zLiAKQXMgd2UgY2FuIHNlZSwgdGhlIHBhbmRlbWljIGFmZmVjdGVkIGRpZmZlcmVudCBzZWN0b3JzIGluIGEgZGlmZmVyZW50IHdheS4gVGhlIGxlYXN0IGFmZmVjdGVkIHNlY3RvcnMgYXJlIENvbW11bmljYXRpb24gRGlzY3JldGlvbmFyeSBhbmQgVGVjaG5vbG9neSwgb25lIG9mIHRoZSByZWFzb25zIGJlaW5nIHRoYXQgdGhlaXIgY29uc3VtcHRpb24gZG9lc24ndCByZXF1aXJlIGluIHBlcnNvbiBwcmVzZW5jZS4gSW4gdGhlIGNhc2Ugb2YgZW5lcmd5LCBhIGRyb3AgaW4gdGhlIGRlbWFuZCBvZiBwZXRyb2xldW0gYXMgYSBjb25zZXF1ZW5jZSBvZiB0aGUgbG9ja2Rvd24gaW4gZGlmZmVyZW50IGNvdW50cmllcyBkZWNyZWFzZWQgdGhlaXIgcHJpY2VzLiBHaXZlbiB0aGF0IG9pbCBjb21wYW5pZXMnIHJldmVudWUgZGVwZW5kcyBvbiBwcmljZSwgdGhlIGludmVzdG9ycyBzb2xkIHRoZWlyIHNoYXJlcyBleHBlY3RpbmcgbG9zc2VzIG9uIHRoZSBvaWwgaW5kdXN0cnkuIFRoZSBGaW5hbmNpYWxzIHNlY3RvciB3YXMgYWxzbyBkcmFzdGljYWxseSBhZmZlY3RlZCwgYXMgdGhlIEZFRCBsb3dlcmVkIHRoZSBpbnRlcmVzdCByYXRlcyBhbmQgdGhlcmUgd2VyZSBuZWdhdGl2ZSBpbnRlcmVzdCByYXRlcyBpbiBFdXJvcGUsIHVuZGVyc3RhbmRpbmcgdGhhdCBiYW5rcyBhcmUgdGhlIHN1cHBsaWVycyBvZiBjYXBpdGFsLCBsb3dlciAob3IgbmVnYXRpdmUpIGludGVyZXN0IHJhdGVzIGFmZmVjdCBiYW5rcycgcmV2ZW51ZS4KCiMjIyBSZXR1cm4gYnkgY29tcGFuaWVzOiAKYGBge3IsIGV2YWw9RkFMU0V9Cm1vdmluZ19yZXR1cm5fY29tcGFueSA8LSBkcm9wX25hKHNwKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZSwgQ29tcGFueSkgJT4lIAogIHNlbGVjdCgtVm9sdW1lLCAtU2VjdG9yKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBncm91cF9ieShEYXRlKSAlPiUgCiAgbXV0YXRlKHJldHVybiA9IHJldHVybiAvIDEwMCkgJT4lIAogIHRvcF9uKG4gPSAxMCwgd3QgPSByZXR1cm4pICU+JSAgCiAgYXJyYW5nZShEYXRlLCByZXR1cm4pICU+JSAKICBtdXRhdGUocmFuayA9IDE6IG4oKSkgJT4lIAogIGdncGxvdChhZXMoeSA9IGZhY3RvcihyYW5rKSwgeCA9IHJldHVybiwKICAgICAgICAgICAgIGZpbGwgPSByZXR1cm4pKSArIAogIGdlb21fY29sKCkgKyAKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gQ29tcGFueSksCiAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwgaGp1c3QgPSAibGVmdCIsIHggPSAwKSArCiAgbGFicyh0aXRsZSA9ICJSYXRlIG9mIHJldHVybiBjaGFuZ2VzIGluIGNvbXBhbmllcyIsCiAgICAgICBzdWJ0aXRsZSA9ICJEYXRlOiB7ZnJhbWVfdGltZX0iLAogICAgICAgeCA9ICIiLAogICAgICAgeSA9ICIiKSArCiAgdGhlbWUoYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSAgKwogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKCkgKyAKICB0cmFuc2l0aW9uX3RpbWUoRGF0ZSkgCmFuaW1hdGUobW92aW5nX3JldHVybl9jb21wYW55LCBuZnJhbWVzID0gMjAwLCBkdXJhdGlvbiA9IDQ1KQphbmltX3NhdmUoIm1vdmluZ19yZXR1cm5fY29tcGFueS5naWYiKQpgYGAKCmBgYHtyLCBlY2hvPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIm1vdmluZ19yZXR1cm5fY29tcGFueS5naWYiKQpgYGAKCldoZW4gd2UgZ28gZGVlcGVyIGludG8gZWFjaCBjb21wYW55IGluIHRoZSBmaWVsZCwgaXQgd2lsbCBiZSBUZXNsYSB0aGF0IGdyb3dzIHRoZSBtb3N0IGR1cmluZyB0aGUgcGVyaW9kLiBUZXNsYeKAmXMgc3RvY2sgcHJpY2UgaGFzIGluY3JlYXNlZCBtb3JlIHRoYW4gOSB0aW1lcyBmb3IgdGhlIHBlcmlvZCwgZm9sbG93ZWQgYnkgTnZpZGlhIGFzIHRoZSBjb21wYW55IHRyaXBsZWQgaW4gdmFsdWUuIEFmdGVyIHRoYXQsIHdlIGNhbiBzZWUgQXBwbGUsIEFtYXpvbiwgTWljcm9zb2Z0IG9yIEZhY2Vib29rIGluY3JlYXNlZCBxdWl0ZSBoZWF2aWx5IGR1cmluZyB0aGUgcGVyaW9kLCBhbGwgaW5jcmVhc2luZyBieSAxMDAtMTUwJS4gR2l2ZW4gdGhhdCB0aGUgRW5lcmd5IGFuZCBGaW5hbmNpYWwgc2VjdG9ycyBkaWQgbm90IHNlZSBhbiBpbmNyZWFzZSBpbiB0aGUgc3RvY2sgcHJpY2UsIGl0IGNvbWVzIGFzIG5vIHN1cnByaXNlIHRoYXQgd2UgY2Fu4oCZdCBzZWUgYW55IGNvbXBhbmllcyBpbiB0aG9zZSBzZWN0b3JzIGluIHRoZSB0b3AgdGVuIGxpc3QuIAoKIFdoZW4gd2UgbG9vayBjbG9zZXIgYXQgdGhlIHNob3J0ZXIgcGVyaW9kLCBpbiBNYXJjaCBvciBBcHJpbCwgd2UgY2FuIHNlZSBXYWxtYXJ0IChvbmUgb2YgdGhlIGNvbXBhbmllcyBpbiB0aGUgQ29uc3VtZXIgU3RhcGxlcyBzZWN0aW9uKSB0aGF0IHdhcyBpbiB0b3AgMTAgY29tcGFuaWVzIHdpdGggdGhlIGdyZWF0ZXN0IHJldHVybi4gSG93ZXZlciwgYWZ0ZXIgdGhpcyBwZXJpb2QsIGl0IHdhcyBzdGlsbCBjb21wYW5pZXMgaW4gQ29tbXVuaWNhdGlvbiBEaXNjcmV0aW9uYXJ5IGFuZCBUZWNobm9sb2d5IHRoYXQgaGF2ZSB0aGUgaGlnaGVzdCByZXR1cm4gc3VjaCBhcyBUZXNsYSwgTnZpZGlhLCBNaWNyb3NvZnQsIEFtYXpvbiBvciBBcHBsZS4gCiAKIyMgVGhlIGNoYW5nZSBpbiBtYXJrZXQgY2FwaXRhbGl6YXRpb24gZm9yIGVhY2ggc2VjdG9yIGFuZCBmb3IgdGhlIGNvbXBhbnk6IAoKYGBge3IgVHJlZW1hcCBHcmFwaCAxLCBldmFsPUZBTFNFfQpsIDwtICJzcXVhcmlmaWVkIgpwMjwtIAogIHNlY3Rvcl9kYXRhICU+JSAKICB1bmdyb3VwKCkgJT4lIAogICMgZmlsdGVyKGRhdGUgPT0gIjIwMjAtMDEtMTAiKSAlPiUKICBnZ3Bsb3QoIGFlcyhhcmVhID0gcGVyY2VudGFnZSAsCiAgICAgICAgICAgICAgZmlsbCA9IHNlY3RvciwgCiAgICAgICAgICAgICAgbGFiZWwgPSBsYWJlbCwKICAgICAgICAgICAgICBncm91cD0gZGF0ZSkpICsKICBnZW9tX3RyZWVtYXAobGF5b3V0ID0gbCkgKwogIGdlb21fdHJlZW1hcF90ZXh0KGxheW91dD1sKSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgTWFya2V0IENhcCBpbiBieSBTZWN0b3IgaW4ge2N1cnJlbnRfZnJhbWV9IikrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSAgICAgKwogIHRyYW5zaXRpb25fbWFudWFsKGRhdGUpCmFuaW1hdGUocDIsIGR1cmF0aW9uID0gMTIwKQoKYW5pbV9zYXZlKCJzcF9tYXJrZXRfY2FwX3RyZWVtYXBfYnlfc2VjdG9yX2FuaW0uZ2lmIikKYGBgCgpgYGB7cn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoInNwX21hcmtldF9jYXBfdHJlZW1hcF9ieV9zZWN0b3JfYW5pbS5naWYiKQpgYGAKCkxvb2tpbmcgYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiBtYXJrZXQgY2FwIGJ5IHNlY3RvciBkdXJpbmcgdGhlIENvdmlkLTE5IHBlcmlvZCwgaXQgaXMgc2VlbiBjbGVhcmx5IHRoYXQgQ29tbXVuaWNhdGlvbiBEaXNjcmV0aW9uYXJ5IGFuZCBUZWNobm9sb2d5IGhhdmUgY29uc2lzdGVudGx5IGJlZW4gdGhlIHRvcCBmaXJzdCBhbmQgc2Vjb25kIGxhcmdlc3Qgc2VjdG9ycyByZXNwZWN0aXZlbHkgd2l0aCBjb21iaW5lZCBzaGFyZXMgYXQgbW9yZSB0aGFuIDYwJS4gVGhlIHR3byBzZWN0b3JzIHJlbWFpbiB0aGUgbGVhZGluZyBzZWN0b3JzIHRocm91Z2hvdXQgdGhlIHBlcmlvZCBmcm9tIEphbnVhcnkgMjAyMCB0byBNYXJjaCAyMDIxLiAKCkNvbnN1bWVyIERpc2NyZXRpb25hcnkgaXMgdGhlIGJpZ2dlc3Qgc2VjdG9yIHdoaWNoIGFjY291bnRzIGZvciBhcm91bmQgNDYlIG9mIHRoZSBlbnRpcmUgbWFya2V0IGNhcC4gVGhlIGhpZ2hlc3QgcGVyY2VudGFnZSBvZiB0aGlzIHNlY3RvciB3YXMgNDkuNzg4OCUgaW4gbGF0ZSBPY3RvYmVyIDIwMjAuIFRoaXMgaW5jcmVhc2luZyB0cmVuZCBzdGFydGVkIGluIEphbnVhcnkgYW5kIGhpdCB0aGUgcGVhayBpbiBPY3RvYmVyIDIwMjAgYmVmb3JlIGhhdmluZyBhIGRlY3JlYXNpbmcgdHJlbmQgZnJvbSBPY3RvYmVyIHRvIE1hcmNoIHRoZSBuZXh0IHllYXIuIFRoZSBuZXh0IHNlY3RvciwgVGVjaG5vbG9neSwgYWxzbyBoYWQgYW4gaW5jcmVhc2luZyBwZXJjZW50YWdlIG92ZXIgdGltZSBhcyB0aGUgYXJlYSBpbiB0aGUgZ3JhcGggaW5jcmVhc2VkLiBUaGlzIHBlcmNlbnRhZ2Ugb2YgbWFya2V0IGNhcCBmb3IgdGhpcyBzZWN0b3Igc3RhcnRlZCBmcm9tIDE5Ljg1JSAgaW4gSmFudWFyeSAyMDIwLCBhdCAyMS40OCUgaW4gdGhlIDFzdCBRdWFydGVyIGluIEFwcmlsIDIwMjAgYW5kIGF0IDI0LjE3JSBpbiBOb3ZlbWJlciAyMDIwLiBUaGUgbWF4IGZvciB0aGlzIHNlY3RvciB3YXMgMjYuODQlLgoKYGBge3IgVHJlZW1hcCBHcmFwaCAyLCBldmFsPUZBTFNFfQpzZWN0b3JfZGF0YSA8LQogIHNwICU+JQogIGNsZWFuX25hbWVzKCkgICU+JQogIGZpbHRlcihzZWN0b3IgIT0gIkFsbCBmaWVsZCIpICU+JQogIGdyb3VwX2J5KGRhdGUsIHNlY3RvcikgJT4lCiAgc3VtbWFyaXNlKG1hcmtldF9jYXAgPSBzdW0obWFya2V0X2NhcCkpICU+JQogIG11dGF0ZShwZXJjZW50YWdlID0gMTAwKm1hcmtldF9jYXAvc3VtKG1hcmtldF9jYXApKSAlPiUKICBtdXRhdGUobGFiZWwgPSBwYXN0ZShzZWN0b3IsIHBhc3RlKHJvdW5kKHBlcmNlbnRhZ2UsMiksIiUiKSwgc2VwPSJcbiIpICkKYGBgCgoKYGBge3IgVHJlZW1hcCBHcmFwaCAzLCBldmFsPUZBTFNFfQpjb21wYW55X2RhdGEgPC0KICBzcCAlPiUgCiAgY2xlYW5fbmFtZXMoKSAlPiUgCiAgZmlsdGVyKHNlY3RvciAhPSAiQWxsIGZpZWxkIikgJT4lCiAgZ3JvdXBfYnkoZGF0ZSwgY29tcGFueSkgJT4lIAogIHN1bW1hcmlzZShtYXJrZXRfY2FwID0gc3VtKG1hcmtldF9jYXApKSAlPiUKICBtdXRhdGUocGVyY2VudGFnZSA9IDEwMCptYXJrZXRfY2FwL3N1bShtYXJrZXRfY2FwKSkgJT4lCiAgbXV0YXRlKGxhYmVsID0gcGFzdGUoY29tcGFueSwgcGFzdGUocm91bmQocGVyY2VudGFnZSwyKSwiJSIpLCBzZXA9IlxuIikgKQogIApwMzwtIAogIGNvbXBhbnlfZGF0YSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICAjIGZpbHRlcihkYXRlID09ICIyMDIwLTAxLTEwIikgJT4lCiAgZ2dwbG90KCBhZXMoYXJlYSA9IHBlcmNlbnRhZ2UgLAogICAgICAgICAgICAgIGZpbGwgPSBjb21wYW55LCAKICAgICAgICAgICAgICBsYWJlbCA9IGxhYmVsLAogICAgICAgICAgICAgIGdyb3VwPSBkYXRlKSkgKwogIGdlb21fdHJlZW1hcCgpICsKICBnZW9tX3RyZWVtYXBfdGV4dCgpICsKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBNYXJrZXQgQ2FwIGJ5IENvbXBhbnkgaW4ge2N1cnJlbnRfZnJhbWV9IikrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSAgICAgKwogIHRyYW5zaXRpb25fbWFudWFsKGRhdGUpCmFuaW1hdGUocDMsIGR1cmF0aW9uID0gMTIwKQoKYW5pbV9zYXZlKCJzcF9tYXJrZXRfY2FwX3RyZWVtYXBfYnlfY29tcGFueV9hbmltLmdpZiIpCmBgYAoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoInNwX21hcmtldF9jYXBfdHJlZW1hcF9ieV9jb21wYW55X2FuaW0uZ2lmIikKYGBgCgpUaGUgZGlzdHJpYnV0aW9uIG9mIG1hcmtldCBjYXAgYnkgY29tcGFueSBncmFwaCBzaG93cyB0aGUgdG9wIDIwIGNvbXBhbmllcyB0aGF0IGhhdmUgdGhlIGdyZWF0ZXN0IGFtb3VudCBvZiBtYXJrZXQgY2FwIHByb3BvcnRpb24uIEFwcGxlIChBQVBMKSwgQW1hem9uIChBTVpOKSwgYW5kIE1pY3Jvc29mdCAoTVNGVCkgYXJlIHRoZSB0b3AgdGhyZWUgY29tcGFuaWVzIHRoYXQgYXJlIGZyb20gdGhlIHRvcCB0d28gc2VjdG9yczogQ29tbXVuaWNhdGlvbiBEaXNjcmV0aW9uYXJ5IGFuZCBUZWNobm9sb2d5LiBGcm9tIHRoaXMgd2UgY2FuIHNlZSBob3cgdGhlIHR3byBzZWN0b3JzIGFyZSB0aGUgZG9taW5hbnQgYnkgbG9va2luZyB3aGljaCBjb21wYW5pZXMgaGF2ZSB0aGUgZ3JlYXRlc3QgbWFya2V0IGNhcC4gCgojIyBUaGUgY2hhbmdlIGluIHRyYWRpbmcgdm9sdW1lIGZvciBlYWNoIHNlY3Rvci4KCmBgYHtyLCBldmFsID0gVFJVRSwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTMuNX0Kdm9sdW1lIDwtIHNwICU+JSAKICBmaWx0ZXIoU2VjdG9yIT0iQWxsIGZpZWxkIikgJT4lIAogIHNlbGVjdCgtQ2xvc2UsIC1yZXR1cm4pICU+JQogIG11dGF0ZShtb250aCA9IG1vbnRoKERhdGUsbGFiZWwgPSBUUlVFKSwKICAgICAgICAgeWVhciA9IHllYXIoRGF0ZSkpICU+JSAKICBncm91cF9ieShTZWN0b3IsIG1vbnRoLCB5ZWFyKSAlPiUgCiAgc3VtbWFyaXplKGBUb3RhbCB2b2x1bWVgID0gc3VtKFZvbHVtZSkpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIG11dGF0ZShkYXRlID0geW1kKHBhc3RlKHllYXIsbW9udGgsIjAxIikpKSAlPiUgCiAgbXV0YXRlKFNlY3RvciA9IGZjdF9yZW9yZGVyKFNlY3RvciwgYFRvdGFsIHZvbHVtZWAsIG1lZGlhbiwgLmRlc2MgPSBUUlVFKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSBgVG90YWwgdm9sdW1lYCwgZmlsbCA9IFNlY3RvcikpKwogIGdlb21fY29sKCkrCiAgbGFicyh0aXRsZSA9ICJNb250aGx5IGFtb3VudCBvZiB0cmFuc2FjdGlvbnMgcGVyIHNlY3RvciBsYXN0IHllYXIiLAogICAgICAgeSA9ICIiLAogICAgICAgeCA9ICIiKSsKICBzY2FsZV94X2RhdGUoZGF0ZV9sYWJlbHMgPSAiJWIiLCBkYXRlX2JyZWFrcyA9ICIzIG1vbnRocyIpKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yLnkgPWVsZW1lbnRfYmxhbmsoKSkrCiAgZmFjZXRfd3JhcCh+U2VjdG9yKQoKZ2dwbG90bHkodm9sdW1lLAogICAgICAgICB0b29sdGlwID0gYygieSIpKQogICAgICAgICAKYGBgCgpUaGUgYmFyIGdyYXBoIHNob3dzIHRoZSBzdW0gb2YgdGhlIG1vbnRobHkgdHJhbnNhY3Rpb25zIGZvciB0aGUgdGhyZWUgYmlnZ2VzdCBjb21wYW5pZXMgaW4gZWFjaCBzZWN0b3IuIFdlIGNhbiBzZWUgdGhhdCB0aGUgc2VjdG9yIHdpdGggdGhlIGhpZ2hlc3Qgdm9sdW1lIGlzIFRlY2hub2xvZ3ksIGFuZCB0aGUgc2VjdG9yIHdpdGggdGhlIGxvd2VzdCB2b2x1bWUgaXMgdGhlIFJlYWwgRXN0YXRlIHNlY3Rvci4gVGhlIGhpZ2ggdm9sdW1lcyBpbiB0aGUgVGVjaG5vbG9neSBzZWN0b3IgcG90ZW50aWFsbHkgcmVmbGVjdCB0aGF0IGludmVzdG9ycyBwcmVmZXJyZWQgbGFyZ2UgdGVjaG5vbG9neSBjb21wYW5pZXMgb3ZlciB0aGUgcGFuZGVtaWMuIApgYGB7cn0KcmVhbF9lc3RhdGUgJT4lIAogIGdncGxvdChhZXMoeCA9IERhdGUsIHkgPSByZXR1cm4sIGNvbG9yID0gQ29tcGFueSkpICsKICBnZW9tX2xpbmUoKSsKICBsYWJzKHRpdGxlID0gIlJlYWwgRXN0YXRlIGJpZ2dlc3QgY29tcGFuaWVzJyByZXR1cm5zIG92ZXIgdGhlIHBhc3QgeWVhciIsCiAgICAgICB5ID0gIlJldHVybiIsIAogICAgICAgeCA9ICIiKQpgYGAKCmBgYHtyfQp0ZWNoICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBEYXRlLCB5ID0gcmV0dXJuLCBjb2xvciA9IENvbXBhbnkpKSArCiAgZ2VvbV9saW5lKCkrCiAgbGFicyh0aXRsZSA9ICJUZWNobm9sb2d5IGJpZ2dlc3QgY29tcGFuaWVzJyByZXR1cm5zIG92ZXIgdGhlIHBhc3QgeWVhciIsCiAgICAgICB5ID0gIlJldHVybiIsIAogICAgICAgeCA9ICIiKQpgYGAKClRoZXNlIGNvbXBhbmllcyBoYXZlIGxhcmdlIG1hcmtldCBjYXBzLCBhbmQgZ2l2ZW4gdGhhdCB0aGUgNSBsYXJnZXN0IGNvbXBhbmllcyBpbiB0aGUgVGVjaG5vbG9neSBzZWN0b3IgYWNjb3VudCBmb3IgYSBsYXJnZSBmcmFjdGlvbiBvZiB0aGUgUyZQIDUwMCwgdGhlc2UgImJsdWUgY2hpcCIgY29tcGFuaWVzIGFyZSBleHBlY3RlZCB0byBoYXZlIGxhcmdlciB2b2x1bWVzLiBPbmUgb2YgdGhlIHJlYXNvbnMgaXMgdGhlaXIgbGlxdWlkaXR5LiBUaGV5IGFyZSB2ZXJ5IGxpcXVpZCBiZWNhdXNlIG1hbnkgcGVvcGxlIGFyZSB0cmFkaW5nIHRoZW07IHRoZXJlZm9yZSwgeW91IGNhbiBmaW5kIGJ1eWVycyBhbmQgc2VsbGVycyBxdWlja2x5LiBBcyBhIHJlc3VsdCB0aGVyZSBhcmUgbm8gcHJpY2UgZGlzdG9ydGlvbnMgYXMgYSBjb25zZXF1ZW5jZSBvZiBkZWxheXMgaW4gdHJhbnNhY3Rpb25zLgpPbiB0aGUgb3RoZXIgaGFuZCwgdGhpcyBjb3VsZCBiZSBqdXN0IGEgY29udGludWF0aW9uIG9mIHBhc3QgdHJlbmRzLCBnaXZlbiB0aGF0IHRoZSB0ZWNobm9sb2d5IHNlY3RvciBoYXMgYmVlbiB0aGUgbW9zdCBwb3B1bGFyIGluIHRoZSBsYXN0IHllYXJzLiAKCkFub3RoZXIgcG90ZW50aWFsIGV4cGxhbmF0aW9uIGlzIHRoYXQgVGVjaG5vbG9neSBzdG9ja3MgYXJlIGFsd2F5cyBtb3JlIHJpc2t5IGdpdmVuIHRoZSBsYXJnZXIgcmV0dXJuczsgdGhlcmVmb3JlLCB0aGVyZSBhcmUgbWFqb3IgcHJpY2Ugc3dpbmdzIHRoYXQgY2F1c2UgcGVvcGxlIHRvIGluY3JlYXNlIHRoZWlyIHRyYW5zYWN0aW9ucy4gCkFsc28sIGxhcmdlciB2b2x1bWVzIHJlZmxlY3QgdGhlIHN0cmVuZ3RoIG9mIHByaWNlIGNoYW5nZXMgZHVyaW5nIHRoZSBwYW5kZW1pYy4gSW4gdGhlIGNhc2Ugb2YgUmVhbCBFc3RhdGUsIGxvdyB2b2x1bWVzIHJlZmxlY3QgdGhlIGxhY2sgb2Ygc3RyZW5ndGggaW4gcHJpY2UgY2hhbmdlcywgcmVmbGVjdGVkIG9uIHN1YnRsZSBjaGFuZ2VzIGluIHRoZSBjdW11bGF0aXZlIHJldHVybnMgZ3JhcGhlZC4gQXMgd2UgY2FuIHNlZSBpbiB0aGUgZ3JhcGggZm9yIFJlYWwgRXN0YXRlIGNvbXBhbmllcywgdGhlIHRyZW5kIGlzIGZsYXR0ZXIgYW5kIHRoZSBjaGFuZ2VzIGFyZSBvZiBhIHNtYWxsZXIgbWFnbml0dWRlLCBwcm92aW5nIHRoYXQgdGhlcmUgd2VyZW4ndCBzaWduaWZpY2FudCBjaGFuZ2VzIGluIHJldHVybi4gVGhlcmVmb3JlLHRoZXJlIHdlcmVuJ3QgbWFueSBjaGFuZ2VzIGluIHRoZSBkZW1hbmQgb3Igc3VwcGx5IG9mIFJlYWwgRXN0YXRlIHN0b2NrLiAgCgpXZSBjYW4gYWxzbyBvYnNlcnZlIHRoYXQgaW4gcGVyaW9kcyB3aXRoIGxvdyBwcmljZXMsIHRoZSB2b2x1bWUgdGVuZHMgdG8gaW5jcmVhc2UuIEluIHRoaXMgY2FzZSwgaXQgd2FzIGluIE1hcmNoIGdpdmVuIHRoZSBkZWNsYXJhdGlvbiBvZiBzYW5pdGFyeSBlbWVyZ2VuY3kgYW5kIHRoZSBmaXJzdCBDT1ZJRC0xOSBjYXNlcyBpbiB0aGUgY291bnRyeS4gVGhpcyBpcyBiZWNhdXNlIG1hbnkgcGVvcGxlIGF0dGVtcHQgdG8gc2VsbCB0aGVpciBzaGFyZXMgcXVpY2tseSB3aGlsZSBvdGhlciBpbnZlc3RvcnMgc2VlayB0byBidXkgc2hhcmVzIGF0IGxvd2VyIHByaWNlcy4gCgojIENvbmNsdXNpb246IAoKVGhlIGZvbGxvd2luZyBwb3N0IGhhcyBzaG93biBzb21lIG9mIHRoZSBrZXkgY2hhbmdlcyB3aXRoaW4gdGhlIHBlcmlvZC4gSXQgaGFzIHNob3duIGhvdyBlYWNoIHNlY3RvciBoYXMgY2hhbmdlZCBhbmQgaG93IGVhY2ggY29tcGFueSByZWFjdHMgdG8gdGhlIHBhbmRlbWljLiBTb21lIGNvbXBhbmllcyB0aHJpdmVkLCBsaWtlIFRlc2xhLCBob3dldmVyLCBzb21lIHRvb2sgbG90cyBvZiB0aW1lIHRvIHJlY292ZXIsIGVzcGVjaWFsbHkgaW4gdGhlIEVuZXJneSBhbmQgRmluYW5jZSBzZWN0b3IuIEZvciB0aGUgbmV4dCBzdGVwcywgd2UgY291bGQgdHJ5IGFuZCBpbXByb3ZlIG91ciBpbmZvcm1hdGlvbiBieSBzY3JhcGluZyBhbmQgZ2V0dGluZyBhbGwgb2YgdGhlIGRhdGEgaW4gZXZlcnkgY29tcGFueSB0byBpbGx1c3RyYXRlIGFuZCBzaG93IHRoZSBiZXN0IHBpY3R1cmUgZm9yIHRoZXNlIHNlY3RvcnMuIFRoaXMgd2lsbCBiZSB0aGUgaW1wcm92ZW1lbnQgdGhhdCB3ZSBtaWdodCBuZWVkIHRvIGRvIHRvIHNlZSB0aGUgd2lkZXIgcGljdHVyZSBvZiB0aGUgbWFya2V0LiAKCk92ZXJhbGwsIG91ciBhbmFseXNpcyBoYXMgc2hvd24gdGhlIGNoYW5nZXMgaW4gc3RvY2sgcHJpY2VzLCB2b2x1bWUsIG1hcmtldCBjYXBpdGFsaXphdGlvbiBiZWZvcmUgYW5kIGFmdGVyIHRoZSBwYW5kZW1pYy4gVGhlIHBhbmRlbWljIGFuZCBpdHMgY29uc2VxdWVuY2VzIG9uIHRoZSBlY29ub215IG1ha2UgaXQgZGlmZmljdWx0IHRvIHByZWRpY3Qgd2hpY2ggY29tcGFuaWVzIHdpbGwgdGhyaXZlIGFuZCBzdWNjZWVkIGluIHRoZSBmdXR1cmUuIEhvd2V2ZXIsIHdlIGhvcGUgdGhhdCBzb21lIG9mIG91ciBmaW5kaW5ncyB3aWxsIHNoZWQgbGlnaHQgb24gc29tZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZ2VuZXJhbCBtYXJrZXQgdHJlbmRzIG9ic2VydmVkIHdoZW4gZGVhbGluZyB3aXRoIGEgZ2xvYmFsIHBhbmRlbWljLiAKCiMjIENvbnRyaWJ1dGlvbiBmb3IgZXZlcnkgbWVtYmVyOiAKCkR1YzogClRvZ2V0aGVyIHdpdGggRnJhbmNvLCBJIGFtIGluIGNoYXJnZSBvZiBzY2hlZHVsaW5nIG91ciBhcHBvaW50bWVudHMsIG1ha2luZyBzdXJlIGV2ZXJ5b25lIGhhcyBjcmVhdGVkIHRoZSBiZXN0IGdyYXBoIHBvc3NpYmxlIGFuZCBmaW5kaW5nIHRoZSBjb3JyZWN0IGZpbmFuY2Ugc291cmNlcy4gTW9yZW92ZXIsIEkgdHJpZWQgbXkgYmVzdCB0byBtYWtlIHN1cmUgb3VyIHByb2plY3RzIGdvIG9uIHRpbWUgYW5kIHNtb290aGx5IGJ5IHNldHRpbmcgdXAgbWlzc2lvbnMgYWZ0ZXIgZXZlcnkgbWVldGluZyBhcyB3ZWxsIGFzIHRoZSBvdmVyYWxsIGdvYWwgZm9yIGVhY2ggc2VjdGlvbi4gSSBhdHRlbmRlZCBhbGwgdGhlIG1lZXRpbmdzIGFuZCBzdXBwb3J0ZWQgbXkgdGVhbW1hdGVzIGlmIG5lZWRlZC4gSSBjcmVhdGVkIHRoZSBtb3ZpbmcgZ3JhcGhzIHdoaWNoIHNob3dzIHRoZSBjaGFuZ2UgaW4gdGhlIHJhdGUgb2YgcmV0dXJuIGZvciBldmVyeSBjb21wYW55IGFuZCBldmVyeSBzZWN0b3IuIFdpdGggdGhlc2UgZ3JhcGhzLCBJIHRyaWVkIHRvIHNlZSB3aGljaCBjb21wYW55IGdlbmVyYXRlcyB0aGUgaGlnaGVzdCByZXR1cm4gZHVyaW5nIHRoZSBwZXJpb2QgYW5kIHdoaWNoIHNlY3RvciBwZXJmb3JtcyB0aGUgYmVzdCBkdXJpbmcgdGhlIHBhbmRlbWljLgoKRnJhbmNvOiAKSSBjb250cmlidXRlZCB0byB0aGUgcHJvamVjdCBieSBzaGFyaW5nIG15IGtub3dsZWRnZSBvbiBkaWZmZXJlbnQgZmluYW5jZSBjb25jZXB0cyBhbmQgdGhlIEFQSSBzb3VyY2VzIHRoYXQgd2UgY291bGQgdXNlLiBJIGFsc28gYXNzZW1ibGVkIHRoZSBkYXRhIHNvIHRoYXQgaXQgd291bGQgYmUgaW4gYSB0aW1lIHNlcmllcyBmb3JtYXQgYW5kIGNyZWF0ZWQgdGhlIGR1bW15IHZhcmlhYmxlIGZvciBlYWNoIHNlY3Rvci4gQWxzbywgSSBtb3RpdmF0ZWQgbXkgZnJpZW5kcyB0byBmb2N1cyBvbiBkaWZmZXJlbnQgYXJlYXMgZW5zdXJpbmcgdGhhdCBncmFwaHMgd291bGRuJ3QgYmUgcmVwZXRpdGl2ZS4gSSBhdHRlbmRlZCBhbGwgdGhlIG1lZXRpbmdzIGFuZCBhY2hpZXZlZCBhbGwgb2YgdGhlIG9iamVjdGl2ZXMgdGhlIGdyb3VwIHNldCBpbiBhIHRpbWVseSBtYW5uZXIuIEkgY3JlYXRlZCB0aGUgYmFyIGdyYXBocyBzaG93aW5nIHRoZSBwcm9wb3J0aW9ucyBvZiBuZWdhdGl2ZSBhbmQgcG9zaXRpdmUgcmV0dXJucywgYXMgd2VsbCBhcyB0aGUgZ3JhcGggc2hvd2luZyB0aGUgbW9udGhseSB2b2x1bWUgb2YgZGlmZmVyZW50IHNlY3RvcnMuIEZvciB0aGUgc2Vjb25kIGdyYXBoIEkgY2hvc2UgdG8gd29yayB3aXRoIHBsb3RseSwgYSB0b29sIHRoYXQgd2UgZGlkbuKAmXQgbGVhcm4gd2l0aCBtdWNoIGRlcHRoIGluIGNsYXNzIGJ1dCB0aGF0IGNhbGxlZCBteSBhdHRlbnRpb24uIEkgbGVhcm5lZCB0byB1c2UgaXQgYW5kIHNoYXJlZCBteSBuZXdseSBhY3F1aXJlZCBrbm93bGVkZ2Ugd2l0aCB0aGUgdGVhbS4gCgpWaWNoeTogCkR1cmluZyB0aGUgc3RhcnQgb2YgdGhlIHByb2plY3QsIGFsb25nIHdpdGggb3RoZXIgdGVhbSBtZW1iZXJzLCBJIHBhcnRpY2lwYXRlZCBpbiBmaW5kaW5nIGEgZGF0YSBzZXQgZm9yIHRoZSBwcm9qZWN0IGFuZCBkb3dubG9hZGluZyBhbmQgcHJlcGFyaW5nIHRoZSBkYXRhIGZvciB0aGUgZ3JhcGhpbmcuIEkgcmVjZWl2ZWQgaGVscCBmcm9tIG15IHRlYW1tYXRlIGluIG1ha2luZyBhbGwgdGhlIGRhdGEgY2xlYW4sIGNvbnNpc3RlbnQgYW5kIHJlYWR5IGZvciBtYW5pcHVsYXRpb24uIEkgYW0gcmVzcG9uc2libGUgZm9yIGNyZWF0aW5nIHBhcnRpdGlvbiBncmFwaHMgZm9yIG1hcmtldCBjYXAgYW5kIHRyYWRlIHJldHVybiBieSBzZWN0b3JzIGFuZCBjb21wYW5pZXMuIENvbnNlcXVlbnRseSwgSSBjcmVhdGVkIHRocmVlIGFuaW1hdGVkIGdyYXBoLCBvbmUgc3RhY2tlZCBiYXIgY2hhcnQgZm9yIHNob3dpbmcgYXZlcmFnZSByZXR1cm4gYnkgc2VjdG9yIG92ZXIgdGltZSwgb25lIHRyZWVtYXAgc2hvd2luZyBtYXJrZXQgY2FwIHBhcnRpdGlvbiBieSBzZWN0b3IgYW5kIG9uZSBtb3JlIHRyZWVtYXAgc2hvd2luZyBtYXJrZXQgY2FwIHBhcnRpdGlvbiBieSBjb21wYW5pZXMgb3ZlciB0aW1lLiAKCk1heDoKSSBjb250cmlidXRlZCB0byB0aGUgZ3JvdXAgYnkgY29tYmluaW5nIHRoZSBjb21wYW5pZXMgaW4gdGhlIEVuZXJneSwgUmVhbCBFc3RhdGUsIGFuZCB4eHggc2VjdG9ycyB0b2dldGhlci4gSSBjYWxjdWxhdGVkIHRoZSByYXRlIG9mIHJldHVybiBvZiB0aGVzZSBjb21wYW5pZXMgc2VwYXJhdGVseSBhbmQgZm91bmQgdGhlaXIgYXZlcmFnZS4gQmVzaWRlcywgSSBhbHNvIGNhbGN1bGF0ZWQgdGhlIEZpcnN0IERheSBtYXJrZXQgQ2FwIG9mIHRoZXNlIGNvbXBhbmllcyBieSBtYXJrZXQgc2hhcmVzLiBGaW5hbGx5LCBJIG1hZGUgYSBmYWNldCB3cmFwIGFuaW1hdGlvbiBncmFwaCBvZiBjaGFuZ2luZyByYXRlIG9mIHJldHVybiBmb3IgZGlmZmVyZW50IHNlY3RvcnMgKEkgdGFrZSB0aGUgYXZlcmFnZSBvZiB0aHJlZSBjb21wYW5pZXMgd2l0aGluIHRoZSBzZWN0b3IpCgoKCgoKCgoKCgoKCgo=